Menu
CoddyTech

回顾:人脸扫描器

本课属于 Coddy Machine Learning 学习旅程的“无监督学习”单元。第 33 课,共 51 课。

challenge icon

挑战

中等

办公室门口的摄像头可能只为每张脸保留 k 个数字;程序会读取 k。起始代码会把 300 张 16 × 16 像素的脸画进 X。

  1. 用 k 个成分拟合 PCA。像下面这样打印保留的方差占比。
  2. 在 axs[0] 上绘制第 0 张脸,并在 axs[1] 上绘制用 k 个数字重建的脸,两者都使用 cmap="gray"。
  3. 在 axs[2] 上使用 cmap="gray_r" 绘制第 1 个成分。显示图像。

换一台摄像头,并输入 4:

Kept: 80.5% of the variance with 4 numbers per face

三张 16 × 16 图片:一张微笑的脸、用 4 个数字重建的稍微平滑一些的脸,以及第 1 个成分,一张白底上的深色脸部轮廓

然后,Coddy 会描述你的三个面板。

亲手试试

import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA


# 绘制 count 张 16×16 像素的人脸:每张人脸用一行 256 个亮度值表示(0 到 1)
def make_faces(count, seed):
    rng = np.random.default_rng(seed)
    cols, rows = np.meshgrid(np.arange(16), np.arange(16))
    faces = []
    for i in range(count):
        light = rng.uniform(0.55, 0.95)
        side = rng.uniform(-0.25, 0.25)
        head = ((cols - 7.5) / 6.2) ** 2 + ((rows - 8) / 7.6) ** 2 < 1
        face = head * (light + side * (cols - 7.5) / 7.5)
        eye_row = rng.uniform(5, 7)
        gap = rng.uniform(2.2, 3.6)
        for eye_col in [7.5 - gap, 7.5 + gap]:
            face = face - 0.7 * np.exp(-((cols - eye_col) ** 2 + (rows - eye_row) ** 2) / 1.2)
        smile = rng.uniform(-2, 2)
        mouth_row = 11.5 - smile * ((cols - 7.5) / 3.5) ** 2
        mouth = np.exp(-((rows - mouth_row) ** 2) / 0.4) * (np.abs(cols - 7.5) < 3.6)
        face = face - 0.6 * mouth + rng.normal(0, 0.04, size=(16, 16))
        faces.append(np.clip(face, 0, 1).flatten())
    return np.round(np.array(faces), 2)


# 门口摄像头拍到的 300 张人脸,以及每张人脸可以保留多少个数字
X = make_faces(300, seed=7)
k = int(input())

# 不要修改下面的代码
fig, axs = plt.subplots(1, 3)
axs[0].set_title("Face")
axs[1].set_title(f"Rebuilt from {k}")
axs[2].set_title("Component 1")

# 在下面编写你的代码

无监督学习中的所有课

自己练习: Python 在线编译器