使用Nvidia GPU运行d2l(Dive into Deep Learning)中的深度学习代码

d2l教程中安装的是cpu版本的pytorch,运行某些使用GPU的代码时会报错。下面就说一下如何配置环境来使用GPU来运行某些代码。

  1. 从nvidia官网下载驱动并安装。
    我下载的文件是:582.66-notebook-win10-win11-64bit-international-dch-whql.exe
    安装完,打开命令行输入:nvidia-smi,能显示信息说明驱动安装成功。
  2. 安装miniconda3。
    官网下载最新版本Miniconda3-latest-Windows-x86_64.exe,安装。
  3. 创建env并安装依赖
    打开Anaconda Prompt, 先同意3个terms of service,执行下面3条命令:
    conda tos accept –override-channels –channel https://repo.anaconda.com/pkgs/main
    conda tos accept –override-channels –channel https://repo.anaconda.com/pkgs/r
    conda tos accept –override-channels –channel https://repo.anaconda.com/pkgs/msys2

创建一个新环境:conda create –name d2l python=3.9 -y
激活上面创建的环境:conda activate d2l

d2l教程上安装的torch的版本是1.12.0,torchvision版本是0.13.0。
在pytorch官网https://pytorch.org/get-started/previous-versions/ 我们能找到下面的这行:
conda install pytorch==1.12.0 torchvision==0.13.0 torchaudio==0.12.0 cudatoolkit=11.3 -c pytorch
我们只需要pytorch和torchvision,不需要torchaudio,所以我们执行:

conda install pytorch==1.12.0 torchvision==0.13.0 cudatoolkit=11.3 -c pytorch
注意:这里我们安装了cudatoolkit,就不需要从nvidia官网下载安装CUDA了。

pip install d2l==0.17.6

  1. 安装vscode
    下载最新版vscode并安装。
    打开vscode,安装python插件。
    ctrl + shift +p ,输入python: select interpreter,选择刚才创建的d2l环境。
    电脑上新建一个目录,作为python工程的目录。
    vscode里打开上面创建的目录。
    新建py文件,粘贴d2l教程里的代码,如6.6小节 卷积神经网络(LeNet)的代码。
  2. 遇到的问题
    运行时遇到以下问题:
    backend = matplotlib.rcParams._get(“backend”)
    AttributeError: ‘RcParams’ object has no attribute ‘_get’

我们在文件最开始加入下面几行就能解决。

import matplotlib
# Patch the missing private method to match the standard public .get method
if not hasattr(matplotlib.rcParams, '_get'):
    matplotlib.rcParams._get = matplotlib.rcParams.get

使用OpenCV进行人脸检测和人脸关键点检测

使用opencv haar cascades级联检测器识别人脸,使用opencv facemark LBF识别人脸关键点。

  1. 在本地电脑新建一个目录(如face_recognition_demo),用来存放新的python项目。创建完成后进入该目录。
    mkdir face_recognition_demo
    cd face_recognition_demo
  2. 为新的python项目建立一个python虚拟环境(在.venv子目录下),并激活。
    python3 -m venv .venv
    source .venv/bin/activate
    激活虚拟环境后,.venv/bin这个目录会加入PATH环境变量的头部,这个目录下包含python, pip等命令。所以后面执行python或pip命令时,就会执行虚拟环境下bin目录里对应的命令。
    如果想关闭虚拟环境,在项目根目录执行:deactivate。
  3. 安装依赖包,准备facemark LBF模型文件,准备人脸照片。
    pip install opencv-contrib-python
    注意:opencv-contrib-python已经包含了opencv核心,所以不需要再安装opencv-python包。2个都安装会造成重复。
    新建model子目录,将lbfmodel.yaml放入其中。
    将人脸照片(这里命名为face9.jpeg),放到项目根目录。
  4. 启动VScode,打开上面的python项目的根目录。新建1个python文件(这里文件名为demo.py)。
    以下列出代码。顺便说一下obsidian里关于代码块的注意事项:
    (1)obsidian里,代码块用3个反引号开始,后面紧跟编程语言的名字(如python),用3个反引号结束。
    (2)粘贴代码到代码块时,如果想保留原先代码里的缩进,粘贴时按住 Command + Shift + V (MacOS系统) 或 Control + Shift + V (windows系统)。
from pathlib import Path

import cv2


def resolve_haarcascade(base_dir: Path) -> str:
    candidates = []

    if hasattr(cv2, "data") and hasattr(cv2.data, "haarcascades"):
        candidates.append(Path(cv2.data.haarcascades) / "haarcascade_frontalface_alt2.xml")

    cv2_root = Path(cv2.__file__).resolve().parent
    print(f"cv2_root:{cv2_root}")
    
    candidates.extend(
        [
            base_dir / "haarcascade_frontalface_alt2.xml",
            Path("/opt/homebrew/Cellar/opencv/4.13.0_10/share/opencv4/haarcascades/haarcascade_frontalface_alt2.xml"),
            cv2_root / "data" / "haarcascade_frontalface_alt2.xml",
            cv2_root.parent.parent.parent / "share" / "opencv4" / "haarcascades" / "haarcascade_frontalface_alt2.xml",
        ]
    )

    for candidate in candidates:
        if candidate.exists():
            return str(candidate)

    raise FileNotFoundError(
        "Cannot find haarcascade_frontalface_alt2.xml. "
        "Download it from https://raw.githubusercontent.com/opencv/opencv/4.x/data/haarcascades/haarcascade_frontalface_alt2.xml "
        "and place it next to demo.py."
    )


def main() -> None:
    base_dir = Path(__file__).resolve().parent
    image_path = base_dir / "face9.jpeg"
    model_path = base_dir / "model" / "lbfmodel.yaml"
    output_path = base_dir / "face9_landmarks.jpg"

    image = cv2.imread(str(image_path))
    if image is None:
        raise FileNotFoundError(f"Cannot read image: {image_path}")

    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    cascade_path = resolve_haarcascade(base_dir)
    detector = cv2.CascadeClassifier(cascade_path)
    if detector.empty():
        raise RuntimeError(f"Failed to load Haar cascade: {cascade_path}")

    faces = detector.detectMultiScale(
        gray,
        scaleFactor=1.1,
        minNeighbors=5,
        minSize=(80, 80),
    )
    if len(faces) == 0:
        raise RuntimeError("No face detected in face4.jpeg")

    facemark = cv2.face.createFacemarkLBF()
    facemark.loadModel(str(model_path))

    ok, landmarks = facemark.fit(gray, faces)
    if not ok:
        raise RuntimeError("Facemark fitting failed")

    for (x, y, w, h), face_landmarks in zip(faces, landmarks):
        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
        # for px, py in face_landmarks[0]:
        #     cv2.circle(image, (int(px), int(py)), 2, (0, 0, 255), -1)
        for i, (px, py) in enumerate(face_landmarks[0]):
            x, y = int(px), int(py)
            cv2.circle(image, (x, y), 2, (0, 0, 255), -1)
            cv2.putText(image, str(i), (x + 2, y - 2),
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1)

    cv2.imwrite(str(output_path), image)

    print(f"Detected {len(faces)} face(s)")
    print(f"Saved result to: {output_path}")


if __name__ == "__main__":
    main()

  1. 运行程序。
    在虚拟环境已经激活的情况下(如未激活,则需要执行上面提及的source命令),在终端或命令行中,在项目的根目录下,执行:python demo.py
    目录下会生成一张标记人脸及人脸关键点的图片。人脸用绿色方框标出,人脸关键点用红色圆点标出,每个关键点会标出序号,从0~67。因为我们使用的是人脸68点标记。

Mac系统 (m系列芯片) 安装d2l (Dive into Deep Learning|动手学深度学习)

  1. 安装miniforge
    不要用文档上说的miniconda。
    下载最新版mac系统arm版本的miniforge,比如:Miniforge3-26.3.2-2-MacOSX-arm64.sh。
    执行bash ./Miniforge3-26.3.2-2-MacOSX-arm64.sh, 默认会安装到/Users/xxx/miniforge3,安装过程中可以自定义安装路径。
  2. 新建1个虚拟环境并激活
    安装miniforge完成后,关闭终端,重新打开一个终端。
    conda create -n d2l python=3.10
    conda activate d2l
    这里,python版本选择3.10,其它版本会报错。
  3. 安装依赖
    conda install pytorch torchvision torchaudio -c pytorch
    pip install d2l
  4. 下载代码并运行
    按照文档,执行以下命令。
    mkdir d2l-zh && cd d2l-zh
    curl https://zh-v2.d2l.ai/d2l-zh-2.0.0.zip -o d2l-zh.zip
    unzip d2l-zh.zip && rm d2l-zh.zip
    cd pytorch
    jupyter notebook
    Web浏览器中打开http://localhost:8888(通常会自动打开)。

使用css创建水平菜单的3种方法

使用html中的<ul>,<li>和<a>等元素创建出的菜单,默认情况下,每个item前面有黑色marker,并且每个item占据一行。如何通过设定css,将其转变为水平菜单?有如下3种方法。

1. 使用float属性:对<li>元素设置CSS: float: left。这样,<li>元素将水平排列,不会换行。注意:使用float时,必须对容器(这里是<ul>)设置overflow:hidden。

      <!DOCTYPE html>
      <html>
      <style>
      ul {
        list-style-type: none;
        margin: 0;
        padding: 0;
        overflow: hidden;
        background-color: #333;
      }
      
      ul li {
        float: left;
      }
      
      ul li a {
        display: block;
        padding: 10px 15px;
        text-decoration: none;
        color: white;
      }
      
      ul li a:hover {
        background-color: red;
      }
      
      
      </style>
      <body>
      
      <ul>
      <li><a href="#">item1</a></li>
      <li><a href="#">item2</a></li>
      <li><a href="#">item3</a></li>
      </ul>
      </body>
      </html>

      2. 将<li>元素设置CSS: display: inline-block。因为<li>是block level元素,会以一个新行开始,并且占用全部宽度。通过对其设置 display: inline-block,它就会变得像inline元素一样,只会占据必要宽度,从而多个<li>元素就能够实现水平排列。

      <!DOCTYPE html>
      <html>
      <style>
      ul {
        list-style-type: none;
        margin: 0;
        padding: 0;
        background-color: #333;
      }
      
      ul li {
        display: inline-block;
      }
      
      ul li a {
        display: block;
        padding: 10px 15px;
        text-decoration: none;
        color: white;
      }
      
      ul li a:hover {
        background-color: red;
      }
      
      
      </style>
      <body>
      
      <ul>
      <li><a href="#">item1</a></li>
      <li><a href="#">item2</a></li>
      <li><a href="#">item3</a></li>
      </ul>
      </body>
      </html>
      

      3. 对<ul>使用flex布局。<ul>包含的<li>就会水平排列。

      <!DOCTYPE html>
      <html>
      <style>
      ul {
        list-style-type: none;
        margin: 0;
        padding: 0;
        background-color: #333;
        display: flex;
      }
      
      ul li a {
        display: block;
        padding: 10px 15px;
        text-decoration: none;
        color: white;
      }
      
      ul li a:hover {
        background-color: red;
      }
      
      
      </style>
      <body>
      
      <ul>
      <li><a href="#">item1</a></li>
      <li><a href="#">item2</a></li>
      <li><a href="#">item3</a></li>
      </ul>
      </body>
      </html>
      

      发表在 CSS

      gogs迁移服务器

      1. 新服务器安装gogs,参考https://cloud.tencent.com/developer/article/1626705。只安装,到浏览器打开3000端口首次设置时停止。
      2. 旧服务器上运行./gogs backup 命令,会生成一个zip文件。
      3. 将zip文件使用scp命令传输到新服务器,使用./gogs restore –from=”zip file name”,恢复数据。
      4. 修改DNS设置,gogs服务器域名指向新服务器ip地址,参考旧服务器nginx配置文件,在新服务器nginx配置文件里设置gogs相关网址。
      5. 浏览器打开gogs网址,登录后右上角“用户设置”-“SSH密钥”,删除旧密钥,重新上传公钥文件内容(以前的公钥文件要保留)。