第一篇:机器学习基础(快速回顾)#
篇章概述#
本篇是计算机视觉学习的基础准备篇,快速回顾机器学习核心概念,为后续深度学习和计算机视觉内容打下基础。
学习目标:
- 理解机器学习的基本概念和分类
- 掌握损失函数、优化器等核心要素
- 了解过拟合与正则化
- 理解传统图像特征提取方法
- 明确深度学习相比传统方法的优势
适合人群:
- 有Python基础,想快速了解机器学习概念
- 准备学习深度学习和计算机视觉
- 需要回顾机器学习基础知识
章节结构#
第1章:机器学习核心概念#
涵盖机器学习的基本分类、损失函数、优化器等核心概念,并通过sklearn实现手写数字分类的实战案例。
关键内容:
- 监督学习 vs 无监督学习
- 损失函数与优化器
- 过拟合与正则化
- 实战:手写数字分类(sklearn)
第2章:从传统特征到深度学习#
介绍传统图像特征提取方法(SIFT、HOG等),解释为什么需要深度学习,并准备深度学习环境。
关键内容:
- 传统图像特征(SIFT、HOG)
- 传统方法的局限性
- 为什么需要深度学习
- 环境准备(PyTorch/TensorFlow)
学习路径#
第1章:机器学习核心概念
↓
理解监督学习/无监督学习
↓
掌握损失函数和优化器
↓
实战:MNIST分类(sklearn)
↓
第2章:从传统特征到深度学习
↓
了解SIFT、HOG等传统特征
↓
理解深度学习的优势
↓
准备深度学习环境
↓
进入第二篇:深度学习基础学习建议#
- 快速回顾:本篇作为快速回顾,不需要深入每个细节
- 动手实践:运行所有代码示例,理解实际效果
- 概念理解:重点理解核心概念,为后续学习打基础
- 环境准备:确保环境配置正确,能够运行所有示例代码
环境要求#
# Python版本
Python 3.10+
# 第1章所需库
pip install scikit-learn numpy matplotlib
# 第2章所需库(传统特征)
pip install opencv-python scikit-image
# 深度学习环境(第2章末尾准备)
pip install torch torchvision # PyTorch
# 或
pip install tensorflow # TensorFlow预计学习时间#
- 第1章:2-3小时
- 第2章:2-3小时
- 总计:4-6小时
后续安排#
完成本篇后,将进入第二篇:深度学习基础,学习神经网络、卷积神经网络等深度学习核心内容。
第1章:机器学习核心概念#
本章概述#
本章快速回顾机器学习的核心概念,包括监督学习与无监督学习的区别、损失函数与优化器的作用、以及如何处理过拟合问题。通过一个完整的手写数字分类实战案例,让你理解机器学习的基本流程。
学习目标:
- 理解监督学习和无监督学习的区别
- 掌握损失函数和优化器的概念
- 了解过拟合与正则化方法
- 完成手写数字分类实战
前置知识:
- Python基础语法
- NumPy基础操作
1.1 机器学习基本分类#
监督学习(Supervised Learning)#
定义:从标注数据中学习输入到输出的映射关系。
特点:
- 训练数据包含输入(特征)和输出(标签)
- 目标是学习一个函数 f(x) = y
- 可以评估模型在已知标签数据上的表现
常见任务:
| 任务类型 | 输出类型 | 典型应用 | 示例 |
|---|---|---|---|
| 分类(Classification) | 离散值 | 图像分类、文本分类 | 猫狗识别、垃圾邮件检测 |
| 回归(Regression) | 连续值 | 价格预测、温度预测 | 房价预测、股票预测 |
代码示例:
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import make_classification
# 生成分类数据
X, y = make_classification(n_samples=100, n_features=20, n_classes=2)
# 监督学习:训练数据包含X和y
model = LogisticRegression()
model.fit(X, y) # 需要标签y
# 预测
predictions = model.predict(X)无监督学习(Unsupervised Learning)#
定义:从未标注数据中发现隐藏的模式和结构。
特点:
- 训练数据只有输入,没有标签
- 目标是发现数据的内在结构
- 难以量化评估模型性能
常见任务:
| 任务类型 | 目标 | 典型应用 | 示例 |
|---|---|---|---|
| 聚类(Clustering) | 分组相似样本 | 客户分群、图像分割 | K-means聚类 |
| 降维(Dimensionality Reduction) | 减少特征数量 | 可视化、压缩 | PCA、t-SNE |
| 异常检测(Anomaly Detection) | 发现异常样本 | 欺诈检测、故障检测 | Isolation Forest |
代码示例:
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs
# 生成聚类数据
X, _ = make_blobs(n_samples=100, n_features=2, centers=3)
# 无监督学习:训练数据只有X
model = KMeans(n_clusters=3)
model.fit(X) # 不需要标签
# 聚类结果
labels = model.predict(X)对比总结#
| 维度 | 监督学习 | 无监督学习 |
|---|---|---|
| 数据标签 | 需要标签 | 不需要标签 |
| 训练目标 | 学习输入到输出的映射 | 发现数据内在结构 |
| 性能评估 | 容易(有标签对比) | 困难(无标准答案) |
| 数据成本 | 高(需要人工标注) | 低(无需标注) |
| 典型应用 | 分类、回归 | 聚类、降维 |
1.2 损失函数与优化器#
损失函数(Loss Function)#
定义:衡量模型预测值与真实值之间差异的函数。
作用:
- 量化模型的预测误差
- 指导模型参数的更新方向
- 不同任务使用不同的损失函数
常见损失函数:
1. 均方误差(MSE)- 回归任务#
$$ \text{MSE} = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2 $$
特点:
- 对异常值敏感(平方放大误差)
- 可导,便于优化
- 适用于回归任务
import numpy as np
def mse_loss(y_true, y_pred):
"""均方误差损失"""
return np.mean((y_true - y_pred) ** 2)
# 示例
y_true = np.array([1.0, 2.0, 3.0])
y_pred = np.array([1.1, 2.2, 2.9])
loss = mse_loss(y_true, y_pred)
print(f"MSE Loss: {loss:.4f}") # 0.02332. 交叉熵(Cross-Entropy)- 分类任务#
二分类(Binary Cross-Entropy):
$$ \text{BCE} = -\frac{1}{n}\sum_{i=1}^{n}[y_i\log(\hat{y}_i) + (1-y_i)\log(1-\hat{y}_i)] $$
多分类(Categorical Cross-Entropy):
$$ \text{CCE} = -\frac{1}{n}\sum_{i=1}^{n}\sum_{j=1}^{C}y_{ij}\log(\hat{y}_{ij}) $$
def binary_cross_entropy(y_true, y_pred):
"""二分类交叉熵"""
epsilon = 1e-15 # 防止log(0)
y_pred = np.clip(y_pred, epsilon, 1 - epsilon)
return -np.mean(y_true * np.log(y_pred) + (1 - y_true) * np.log(1 - y_pred))
# 示例
y_true = np.array([1, 0, 1])
y_pred = np.array([0.9, 0.1, 0.8])
loss = binary_cross_entropy(y_true, y_pred)
print(f"BCE Loss: {loss:.4f}") # 0.1336损失函数选择:
| 任务类型 | 推荐损失函数 | 原因 |
|---|---|---|
| 二分类 | Binary Cross-Entropy | 衡量概率分布差异 |
| 多分类 | Categorical Cross-Entropy | 适合softmax输出 |
| 回归 | MSE / MAE | 衡量数值差异 |
| 排序 | Hinge Loss | 最大化分类间隔 |
优化器(Optimizer)#
定义:根据损失函数的梯度更新模型参数的算法。
核心思想:通过迭代更新参数,使损失函数最小化。
梯度下降(Gradient Descent)#
基本公式:
$$ \theta_{t+1} = \theta_t - \eta \cdot \nabla_\theta L(\theta_t) $$
其中:
- $\theta$:模型参数
- $\eta$:学习率(learning rate)
- $\nabla_\theta L$:损失函数对参数的梯度
变体对比:
| 优化器 | 每次更新使用的数据 | 特点 | 适用场景 |
|---|---|---|---|
| 批量梯度下降(BGD) | 全部数据 | 稳定但慢 | 小数据集 |
| 随机梯度下降(SGD) | 单个样本 | 快但不稳定 | 在线学习 |
| 小批量梯度下降(Mini-batch GD) | 小批量数据 | 平衡速度和稳定性 | 最常用 |
常见优化器#
1. SGD(Stochastic Gradient Descent)
# sklearn中的SGD示例
from sklearn.linear_model import SGDClassifier
model = SGDClassifier(
loss='log_loss', # 损失函数
learning_rate='constant', # 学习率策略
eta0=0.01, # 初始学习率
max_iter=1000
)2. Adam(Adaptive Moment Estimation)
特点:
- 结合动量(Momentum)和自适应学习率
- 对每个参数使用不同的学习率
- 最常用的优化器之一
优势:
- 收敛速度快
- 对超参数不敏感
- 适合大多数深度学习任务
优化器选择建议:
| 场景 | 推荐优化器 | 原因 |
|---|---|---|
| 快速原型 | Adam | 收敛快,调参少 |
| 最优性能 | SGD + Momentum | 泛化能力好 |
| 稀疏数据 | AdaGrad | 自适应学习率 |
| RNN/LSTM | Adam / RMSprop | 处理梯度消失 |
1.3 过拟合与正则化#
过拟合(Overfitting)#
定义:模型在训练集上表现很好,但在测试集上表现差。
表现:
- 训练误差很低
- 测试误差很高
- 模型记住了训练数据,而非学习了通用模式
原因:
- 模型过于复杂(参数太多)
- 训练数据太少
- 训练时间过长
示例图示:
训练误差和测试误差随模型复杂度变化:
误差
↑
| 测试误差
| /‾‾‾‾‾
| /
| /
| /
| /_________ 训练误差
|
└─────────────────→ 模型复杂度
↑
最佳复杂度欠拟合(Underfitting)#
定义:模型过于简单,无法捕捉数据的模式。
表现:
- 训练误差高
- 测试误差高
- 模型能力不足
正则化(Regularization)#
目的:防止过拟合,提高模型泛化能力。
1. L1正则化(Lasso)#
公式:
$$ L = L_{\text{original}} + \lambda\sum_{i}|\theta_i| $$
特点:
- 惩罚参数的绝对值
- 产生稀疏解(部分参数为0)
- 可用于特征选择
from sklearn.linear_model import Lasso
# L1正则化
model = Lasso(alpha=0.1) # alpha是正则化强度2. L2正则化(Ridge)#
公式:
$$ L = L_{\text{original}} + \lambda\sum_{i}\theta_i^2 $$
特点:
- 惩罚参数的平方
- 参数趋向于小值但不为0
- 更常用,数值稳定
from sklearn.linear_model import Ridge
# L2正则化
model = Ridge(alpha=1.0) # alpha是正则化强度3. Elastic Net(L1 + L2)#
公式:
$$ L = L_{\text{original}} + \lambda_1\sum_{i}|\theta_i| + \lambda_2\sum_{i}\theta_i^2 $$
from sklearn.linear_model import ElasticNet
# L1 + L2正则化
model = ElasticNet(alpha=0.1, l1_ratio=0.5) # l1_ratio控制L1和L2的比例正则化方法对比:
| 方法 | 惩罚项 | 特点 | 适用场景 |
|---|---|---|---|
| L1 | 绝对值 | 稀疏解,特征选择 | 高维稀疏数据 |
| L2 | 平方 | 平滑解,数值稳定 | 大多数场景 |
| Elastic Net | L1+L2 | 结合两者优势 | 特征相关性高 |
| Dropout | 随机失活 | 集成效果 | 深度神经网络 |
其他防止过拟合的方法#
| 方法 | 原理 | 优点 | 缺点 |
|---|---|---|---|
| 数据增强 | 增加训练样本 | 提高泛化能力 | 需要领域知识 |
| Early Stopping | 提前停止训练 | 简单有效 | 需要验证集 |
| Dropout | 随机丢弃神经元 | 集成效果 | 仅用于神经网络 |
| 交叉验证 | 多次划分数据 | 充分利用数据 | 计算成本高 |
1.4 实战:手写数字分类(sklearn)#
项目概述#
使用scikit-learn实现MNIST手写数字分类,这是机器学习领域的"Hello World"项目。
数据集:MNIST手写数字数据集
- 60,000个训练样本
- 10,000个测试样本
- 每个图像28×28像素,灰度图
- 10个类别(数字0-9)
目标:
- 加载和探索MNIST数据
- 训练多个分类器
- 评估模型性能
- 可视化结果
完整代码#
代码文件:code/chapter01_ml_basics/mnist_sklearn.py
# 详见 code/chapter01_ml_basics/mnist_sklearn.py运行步骤#
# 1. 安装依赖
pip install scikit-learn numpy matplotlib
# 2. 运行代码
cd chapter01/code
python mnist_sklearn.py预期输出#
数据集信息:
训练集: 60000 samples
测试集: 10000 samples
图像尺寸: 28x28
模型性能比较:
Logistic Regression - 准确率: 92.50%
Random Forest - 准确率: 96.80%
SVM - 准确率: 94.20%
最佳模型: Random Forest代码详解#
1. 数据加载#
from sklearn.datasets import fetch_openml
# 加载MNIST数据集
mnist = fetch_openml('mnist_784', version=1, parser='auto')
X, y = mnist.data, mnist.target关键点:
fetch_openml从OpenML下载数据集- 数据已经展平为784维向量(28×28)
- 标签为字符串,需要转换为整数
2. 数据预处理#
# 归一化
X = X / 255.0
# 划分训练集和测试集
X_train, X_test = X[:60000], X[60000:]
y_train, y_test = y[:60000], y[60000:]为什么归一化:
- 特征值范围统一(0-1)
- 加速模型收敛
- 防止某些特征主导
3. 模型训练#
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(max_iter=100)
model.fit(X_train, y_train)逻辑回归要点:
- 虽然名为"回归",但用于分类
- 多分类使用one-vs-rest策略
max_iter控制最大迭代次数
4. 模型评估#
from sklearn.metrics import accuracy_score, classification_report
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print(f"准确率: {accuracy:.2%}")评估指标:
- 准确率(Accuracy):正确预测的比例
- 精确率(Precision):预测为正的样本中真正为正的比例
- 召回率(Recall):真正为正的样本中被正确预测的比例
- F1分数:精确率和召回率的调和平均
实验结果分析#
不同模型对比:
| 模型 | 准确率 | 训练时间 | 优点 | 缺点 |
|---|---|---|---|---|
| Logistic Regression | ~92% | 快 | 简单,可解释 | 性能一般 |
| Random Forest | ~97% | 中 | 性能好,鲁棒 | 模型较大 |
| SVM | ~94% | 慢 | 泛化能力强 | 训练慢 |
提升性能的方法:
- 特征工程:提取更好的特征
- 模型调参:调整超参数
- 集成学习:组合多个模型
- 深度学习:使用CNN(下一篇)
本章小结#
核心概念回顾#
机器学习分类:
- 监督学习:有标签,学习映射关系
- 无监督学习:无标签,发现数据结构
损失函数:
- 衡量模型预测误差
- 回归任务:MSE、MAE
- 分类任务:交叉熵
优化器:
- 根据梯度更新参数
- SGD、Adam等常用优化器
- 学习率是关键超参数
过拟合与正则化:
- 过拟合:训练好测试差
- 正则化:L1、L2、Dropout
- 其他方法:数据增强、Early Stopping
实战经验#
- MNIST分类:传统机器学习可达到~97%准确率
- 模型选择:Random Forest在sklearn中表现最好
- 局限性:传统方法难以处理复杂图像任务
下一章预告#
第2章将介绍传统图像特征(SIFT、HOG),并解释为什么需要深度学习来突破传统方法的局限。
扩展阅读#
- scikit-learn官方文档:https://scikit-learn.org/
- MNIST数据集:http://yann.lecun.com/exdb/mnist/
- 机器学习实战:《Hands-On Machine Learning》
练习题#
- 修改代码:尝试不同的正则化参数,观察对准确率的影响
- 特征工程:提取新特征(如像素均值、方差),看能否提升性能
- 可视化:绘制混淆矩阵,分析哪些数字容易混淆
- 挑战:使用PCA降维到50维,观察性能变化
下一章:第2章:从传统特征到深度学习
第2章:从传统特征到深度学习#
本章概述#
本章介绍传统图像特征提取方法(如SIFT、HOG),分析这些方法的优势和局限性,并解释为什么深度学习能够突破这些限制。最后,我们将准备深度学习环境,为后续章节做好准备。
学习目标:
- 理解传统图像特征提取方法(SIFT、HOG)
- 了解传统方法的优势和局限性
- 理解深度学习相比传统方法的优势
- 配置PyTorch/TensorFlow环境
前置知识:
- 基本的图像处理概念
- Python和NumPy基础
- 第1章的机器学习知识
2.1 传统图像特征#
什么是特征?#
定义:特征是图像中具有区分性的、可以用数值表示的信息。
好特征的标准:
- 可区分性:不同类别的特征值差异大
- 不变性:对光照、旋转、尺度变化鲁棒
- 可计算性:能够高效计算
- 紧凑性:用较少的数值表示丰富的信息
传统方法的核心思想:
原始图像 → 手工设计的特征提取器 → 特征向量 → 分类器 → 预测结果2.1.1 SIFT(Scale-Invariant Feature Transform)#
发明者:David Lowe (1999)
核心思想:检测图像中的关键点,并计算具有尺度和旋转不变性的特征描述子。
主要步骤:
尺度空间极值检测
- 使用高斯差分(DoG)在不同尺度上寻找关键点
- 对尺度变化具有不变性
关键点定位
- 精确定位关键点的位置和尺度
- 去除低对比度和边缘响应的关键点
方向分配
- 计算关键点的主方向
- 实现旋转不变性
关键点描述
- 计算128维特征向量
- 描述关键点周围的梯度分布
特点:
| 特性 | 说明 |
|---|---|
| 尺度不变性 | 对图像缩放鲁棒 |
| 旋转不变性 | 对图像旋转鲁棒 |
| 亮度不变性 | 对光照变化鲁棒 |
| 特征维度 | 128维向量 |
| 计算速度 | 较慢 |
应用场景:
- 图像匹配和拼接
- 物体识别
- 3D重建
- 图像检索
代码示例:
import cv2
import numpy as np
import matplotlib.pyplot as plt
def detect_sift_features(image_path):
"""
使用SIFT检测和提取特征
Args:
image_path: 图像路径
"""
# 读取图像(灰度)
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
# 创建SIFT检测器
sift = cv2.SIFT_create()
# 检测关键点和计算描述子
keypoints, descriptors = sift.detectAndCompute(img, None)
# 绘制关键点
img_keypoints = cv2.drawKeypoints(
img,
keypoints,
None,
flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
)
print(f"检测到 {len(keypoints)} 个关键点")
print(f"描述子维度: {descriptors.shape}")
# 显示结果
plt.figure(figsize=(12, 6))
plt.imshow(img_keypoints, cmap='gray')
plt.title(f'SIFT关键点 (共{len(keypoints)}个)')
plt.axis('off')
plt.tight_layout()
plt.savefig('sift_keypoints.png', dpi=150, bbox_inches='tight')
plt.close()
return keypoints, descriptors
# 使用示例
# keypoints, descriptors = detect_sift_features('image.jpg')2.1.2 HOG(Histogram of Oriented Gradients)#
发明者:Navneet Dalal & Bill Triggs (2005)
核心思想:统计图像局部区域的梯度方向直方图,作为特征描述子。
主要步骤:
计算梯度
- 计算图像每个像素的梯度幅值和方向
- 使用Sobel算子或简单差分
划分单元格(Cell)
- 将图像划分为小的单元格(如8×8像素)
- 每个单元格计算梯度方向直方图
构建块(Block)
- 将多个单元格组成块(如2×2个单元格)
- 在块内进行归一化,提高鲁棒性
特征向量
- 连接所有块的直方图形成最终特征向量
- 典型维度:几千维
特点:
| 特性 | 说明 |
|---|---|
| 光照不变性 | 对亮度变化较鲁棒 |
| 几何不变性 | 对小范围的几何变形鲁棒 |
| 特征维度 | 通常几千维 |
| 计算速度 | 较快 |
| 适用任务 | 行人检测、物体检测 |
应用场景:
- 行人检测(经典应用)
- 物体检测
- 姿态估计
- 动作识别
代码示例:
from skimage.feature import hog
from skimage import exposure
import matplotlib.pyplot as plt
def extract_hog_features(image, visualize=True):
"""
提取HOG特征
Args:
image: 输入图像(灰度)
visualize: 是否可视化
Returns:
features: HOG特征向量
hog_image: HOG可视化图像(如果visualize=True)
"""
# 提取HOG特征
features, hog_image = hog(
image,
orientations=9, # 梯度方向的bins数量
pixels_per_cell=(8, 8), # 每个cell的像素数
cells_per_block=(2, 2), # 每个block的cell数
visualize=visualize,
block_norm='L2-Hys' # 归一化方法
)
if visualize:
# 增强对比度以便可视化
hog_image_rescaled = exposure.rescale_intensity(
hog_image,
in_range=(0, 10)
)
# 显示原图和HOG特征
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))
ax1.imshow(image, cmap='gray')
ax1.set_title('原始图像')
ax1.axis('off')
ax2.imshow(hog_image_rescaled, cmap='gray')
ax2.set_title('HOG特征可视化')
ax2.axis('off')
plt.tight_layout()
plt.savefig('hog_features.png', dpi=150, bbox_inches='tight')
plt.close()
print(f"HOG特征维度: {len(features)}")
return features, hog_image if visualize else None
# 使用示例
# features, hog_img = extract_hog_features(gray_image)2.1.3 其他传统特征#
| 特征类型 | 主要用途 | 特点 |
|---|---|---|
| SURF | 图像匹配 | SIFT的加速版本,使用积分图 |
| ORB | 实时应用 | 快速、免费,结合FAST和BRIEF |
| LBP | 纹理分类 | 计算简单,对光照鲁棒 |
| 颜色直方图 | 图像检索 | 简单高效,忽略空间信息 |
| 边缘特征 | 形状检测 | Canny、Sobel等边缘检测 |
2.1.4 传统特征的优势#
1. 可解释性强
- 特征提取过程清晰
- 容易理解和调试
- 可以根据领域知识设计
2. 计算效率高
- 不需要大量训练数据
- 推理速度快
- 适合资源受限的场景
3. 特定任务表现好
- HOG在行人检测上效果优秀
- SIFT在图像匹配上非常可靠
- 在小数据集上可能优于深度学习
代码示例:传统方法的完整流程
详见:code/chapter02_traditional_cv/traditional_features.py
2.2 传统方法的局限性#
2.2.1 特征工程的困境#
问题1:需要领域专家
- 设计好的特征需要丰富的经验
- 不同任务需要不同的特征
- 特征设计是一个试错过程
问题2:泛化能力有限
- 为特定任务设计的特征难以迁移
- 对新场景的适应性差
- 需要重新设计特征
问题3:特征表达能力不足
传统方法:
图像 → 手工特征(数百到数千维)→ 分类器
深度学习:
图像 → 自动学习特征(数百万参数)→ 分类2.2.2 复杂场景下的失效#
场景1:复杂背景
- 传统特征容易受背景干扰
- 难以区分前景和背景
- 需要额外的预处理
场景2:多样性变化
| 变化类型 | 传统方法应对 | 效果 |
|---------|------------|------|
| 光照变化 | 归一化、不变特征 | 中等 |
| 尺度变化 | 多尺度检测 | 较好 |
| 视角变化 | 3D特征、视角不变性 | 较差 |
| 遮挡 | 局部特征 | 较差 |
| 类内变化 | 特征选择 | 较差 |场景3:高级语义理解
- 传统特征难以捕捉高级语义
- 无法理解上下文关系
- 对抽象概念的表达能力弱
2.2.3 性能瓶颈#
实验数据对比(ImageNet数据集):
| 方法 | Top-5错误率 | 年份 |
|---|---|---|
| 传统方法(SIFT+SVM) | ~25% | 2012前 |
| AlexNet(深度学习) | 15.3% | 2012 |
| ResNet-152 | 3.6% | 2015 |
| 人类水平 | ~5% | - |
关键观察:
- 2012年AlexNet的出现是转折点
- 深度学习在大规模数据集上显著优于传统方法
- 持续改进,已接近甚至超越人类水平
2.3 为什么需要深度学习?#
2.3.1 自动特征学习#
传统方法 vs 深度学习:
传统方法:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 原始图像 │ → │ 手工特征 │ → │ 分类器 │
└──────────┘ └──────────┘ └──────────┘
↑
需要人工设计
深度学习:
┌──────────┐ ┌──────────────────────┐ ┌──────────┐
│ 原始图像 │ → │ 自动学习的特征层级 │ → │ 分类器 │
└──────────┘ └──────────────────────┘ └──────────┘
低级特征 → 中级特征 → 高级特征
↑
端到端学习优势:
- 自动化:不需要手工设计特征
- 层次化:自动学习从低级到高级的特征层次
- 端到端:直接从原始数据到最终输出
2.3.2 表达能力强大#
特征层次的自动学习:
卷积神经网络(CNN)的特征层次:
第1层(低级特征):
- 边缘检测器
- 颜色斑点
- 简单纹理
第2-3层(中级特征):
- 简单形状
- 纹理组合
- 局部模式
第4-5层(高级特征):
- 物体部件(眼睛、轮子等)
- 复杂模式
- 语义概念可视化示例(概念图):
输入图像(猫)
↓
[第1层] 边缘、纹理
↓
[第2层] 简单形状
↓
[第3层] 猫的局部特征(耳朵、眼睛)
↓
[第4层] 猫的整体特征
↓
输出:猫(95%置信度)2.3.3 可扩展性#
数据规模的影响:
性能
↑
| 深度学习
| /
| /
| /
| /______ 传统方法(性能饱和)
| /
| /
|/
└─────────────────────→ 数据量关键点:
- 小数据:传统方法可能更好(避免过拟合)
- 中等数据:两者接近
- 大数据:深度学习显著优于传统方法
2.3.4 迁移学习能力#
传统方法:
- 特征通常针对特定任务
- 难以在不同任务间迁移
深度学习:
- 预训练模型可以迁移到新任务
- 只需微调少量参数
- 大大减少训练数据需求
示例:
# 使用预训练的ResNet模型
import torchvision.models as models
# 加载ImageNet预训练模型
resnet = models.resnet50(pretrained=True)
# 只替换最后一层用于新任务
num_classes = 10 # 新任务的类别数
resnet.fc = nn.Linear(resnet.fc.in_features, num_classes)
# 只训练最后一层,其他层使用预训练权重
for param in resnet.parameters():
param.requires_grad = False
resnet.fc.weight.requires_grad = True
resnet.fc.bias.requires_grad = True2.3.5 深度学习的优势总结#
| 维度 | 传统方法 | 深度学习 |
|---|---|---|
| 特征提取 | 手工设计 | 自动学习 |
| 表达能力 | 有限(数百到数千维) | 强大(数百万参数) |
| 数据需求 | 少 | 多(或使用预训练模型) |
| 可解释性 | 强 | 较弱(黑盒) |
| 泛化能力 | 特定任务 | 跨任务迁移 |
| 性能上限 | 较低 | 高(接近人类) |
| 计算资源 | 少 | 多(需要GPU) |
2.4 环境准备#
2.4.1 PyTorch环境配置#
PyTorch简介:
- Facebook开发的深度学习框架
- 动态计算图,灵活易用
- 学术界最流行的框架
安装步骤:
# 1. 创建虚拟环境(推荐)
python -m venv cv_env
source cv_env/bin/activate # Windows: cv_env\Scripts\activate
# 2. 安装PyTorch(根据CUDA版本选择)
# CPU版本
pip install torch torchvision torchaudio
# GPU版本(CUDA 11.8)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# GPU版本(CUDA 12.1)
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
# 3. 安装其他依赖
pip install numpy matplotlib opencv-python scikit-image验证安装:
import torch
import torchvision
print(f"PyTorch版本: {torch.__version__}")
print(f"TorchVision版本: {torchvision.__version__}")
print(f"CUDA可用: {torch.cuda.is_available()}")
if torch.cuda.is_available():
print(f"CUDA版本: {torch.version.cuda}")
print(f"GPU设备: {torch.cuda.get_device_name(0)}")预期输出:
PyTorch版本: 2.1.0+cu118
TorchVision版本: 0.16.0+cu118
CUDA可用: True
CUDA版本: 11.8
GPU设备: NVIDIA GeForce RTX 30802.4.2 TensorFlow环境配置(可选)#
TensorFlow简介:
- Google开发的深度学习框架
- 工业界广泛使用
- 提供TensorFlow Lite用于移动端部署
安装步骤:
# 安装TensorFlow(包含GPU支持)
pip install tensorflow
# 验证安装
python -c "import tensorflow as tf; print(f'TensorFlow版本: {tf.__version__}'); print(f'GPU可用: {len(tf.config.list_physical_devices(\"GPU\"))}')"本教程选择:
- 主要使用PyTorch
- 原因:代码更直观、调试更方便、学术界主流
2.4.3 完整环境配置脚本#
创建requirements.txt:
# 深度学习框架
torch>=2.0.0
torchvision>=0.15.0
torchaudio>=2.0.0
# 图像处理
opencv-python>=4.8.0
scikit-image>=0.21.0
Pillow>=10.0.0
# 数据处理
numpy>=1.24.0
pandas>=2.0.0
matplotlib>=3.7.0
seaborn>=0.12.0
# 机器学习工具
scikit-learn>=1.3.0
# 进度条和可视化
tqdm>=4.65.0
tensorboard>=2.13.0
# Jupyter支持
jupyter>=1.0.0
ipywidgets>=8.0.0安装:
pip install -r requirements.txt2.4.4 环境测试代码#
详见:code/chapter02_traditional_cv/test_environment.py
运行测试:
cd chapter02/code
python test_environment.py预期输出:
========================================
环境测试开始
========================================
[测试1] PyTorch安装
✓ PyTorch版本: 2.1.0+cu118
✓ CUDA可用: True
✓ GPU设备: NVIDIA GeForce RTX 3080
[测试2] 张量操作
✓ CPU张量创建成功
✓ GPU张量创建成功
✓ 张量运算正确
[测试3] 图像处理库
✓ OpenCV版本: 4.8.0
✓ scikit-image可用
[测试4] 数据加载
✓ MNIST数据集加载成功
✓ 数据形状: torch.Size([1, 28, 28])
========================================
所有测试通过!环境配置成功。
========================================2.5 第一个深度学习示例#
简单的神经网络#
为了对比传统方法和深度学习,我们用一个简单的神经网络重新实现MNIST分类。
代码示例(概览,详细代码见code/chapter02_traditional_cv/simple_nn_mnist.py):
import torch
import torch.nn as nn
# 定义简单的全连接神经网络
class SimpleNN(nn.Module):
def __init__(self):
super(SimpleNN, self).__init__()
self.fc1 = nn.Linear(28 * 28, 128)
self.relu = nn.ReLU()
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = x.view(-1, 28 * 28) # 展平
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
return x
# 训练模型
model = SimpleNN()
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
# 训练循环(简化版)
for epoch in range(10):
for images, labels in train_loader:
outputs = model(images)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()性能对比:
| 方法 | 准确率 | 训练时间 |
|---|---|---|
| Logistic Regression | ~92% | 快 |
| Random Forest | ~97% | 中 |
| 简单神经网络 | ~98% | 中(GPU加速) |
| CNN(下一篇) | ~99%+ | 快(GPU加速) |
本章小结#
核心知识点#
传统特征方法:
- SIFT:尺度和旋转不变,用于图像匹配
- HOG:梯度方向直方图,用于物体检测
- 优势:可解释、高效、特定任务表现好
- 局限:需要人工设计、泛化能力有限
深度学习的优势:
- 自动特征学习,端到端训练
- 强大的表达能力和层次化特征
- 在大数据集上性能优越
- 支持迁移学习
环境准备:
- PyTorch是本教程的主要框架
- 配置GPU加速(推荐)
- 验证环境安装成功
从传统到深度学习的转变#
传统计算机视觉流程:
图像 → 预处理 → 特征提取(手工) → 分类器 → 结果
深度学习流程:
图像 → 神经网络(端到端) → 结果
↓
自动学习特征下一步学习#
完成本章后,你已经:
- ✓ 理解了传统图像特征方法
- ✓ 明白了为什么需要深度学习
- ✓ 配置好了深度学习环境
第二篇预告:深度学习基础
- 神经网络基础
- 反向传播算法
- 卷积神经网络(CNN)
- 经典CNN架构
扩展阅读#
- SIFT原始论文:Lowe, D. G. (2004). “Distinctive Image Features from Scale-Invariant Keypoints”
- HOG原始论文:Dalal, N., & Triggs, B. (2005). “Histograms of oriented gradients for human detection”
- PyTorch官方教程:https://pytorch.org/tutorials/
- Deep Learning Book:http://www.deeplearningbook.org/
练习题#
- 实践:运行
traditional_features.py,比较SIFT和HOG在不同图像上的表现 - 实验:使用HOG特征+SVM训练MNIST分类器,对比第1章的结果
- 环境:确保
test_environment.py所有测试通过 - 思考:为什么SIFT适合图像匹配,而HOG适合物体检测?
下一篇:第二篇:深度学习基础