Task01:初识深度学习(3月19日)
1.1 深度学习应用场景
- NLP:计算机能够解读、处理和理解人类语言,分为认知、理解、生成等部分。如机器翻译、信息提取、语言生成、文本分类、情感分析、智能问答等。
- AIoT:通过物联网产生、收集来自不同维度的、海量的数据存储于云端、边缘端,再通过大数据分析,以及更高形式的人工智能,实现万物数据化、万物智联化。
- 时间序列分析&异常检测(AIOps)
- 语音识别:将人类的语音中的词汇内容转换为计算机可读的输入,例如二进制编码或字符序列。
- AI4Science:蛋白质预测等
- ReinforceLearning:如何基于环境而行动,以取得最大化的预期利益,是第三种基本的机器学习方法。游戏、控制、智慧交通、推荐系统等。
- ChatGPT:
- 交叉方向(AI+)
1.2 深度学习中的小技巧
待补充
1.3 深度学习中的易错点Top5
- 错误的张量形状:例如错误地计算了每一层的输出
- 对输入/标签的预处理不正确:例如忘记归一/标准化,或进行过多的预处理
- 对损失函数的定义不正确:例如Softmax的多分类输出,使用对数损失函数
- 忘记正确设置网络的训练模式:例如切换训练/评估部分
- 数值问题(即inf/Nan):通常源于使用exp、log或div操作
1.4 过拟合overfitting & 欠拟合underfitting
1.5 解决欠拟合(减少偏差)的方法:
欠拟合指模型在训练集、验证集和测试集上均表现不佳。
- 增加模型复杂度(例如增加层数;每层有更多的filters)
- 增加特征数量,使输入数据具有更强的表达能力
- 减少正则化(例如dropout或L1、L2正则化)
- 错误分析(即了解出问题的根因)
- 选择不同的(最先进的)模型结构(例如从VGG16转为Resnet)
- 调整超参数(例如学习率)
1.6 解决过拟合(减少方差)的方法:
过拟合指模型在训练集上表现好,但验证集和测试集表现差,即模型的泛化能力差。
- 添加更多的训练数据
- 添加规范化(例如Batch Norm,Layer Norm)
- 使用数据增强
- 使用正则化约束(例如dropout,L2正则)
- 错误分析
- 选择不同的(最先进的)模型架构
- 调整超参数(例如学习率)
- Early stop 提前结束训练
- 删除部分特征
- 降低模型复杂度
- 使用bagging策略
- 交叉验证
环境配置见PPT,待自行补充
Task02:预备知识(3月20日-21日)
2.1 数据操作
N维数组是机器学习和神经网络的主要数据结构。N维数组示例:
- 0-d(标量):1.0 一个类别
- 1-d(向量):[1.0, 2.7, 3.4] 一个特征向量
- 2-d(矩阵):[[1.0, 2.7, 3.4] [5.0, 0.2, 4.6] [4.3, 8.5, 0.2]] 一个样本-特征矩阵
- 3-d:RGB图片(宽 * 高 * 通道)
- 4-d:一个RGB图片批量(批量大小 * 宽 * 高 * 通道)
- 5-d:一个视频批量(批量大小 * 时间 * 宽 * 高 * 通道)
创建数组需要: - 形状:例如3 * 4矩阵;
- 每个元素的数据类型:例如32位浮点数;
- 每个元素的值,例如全是0,或者随机数。
访问元素: - 一个元素:[1, 2]
- 一行:[1, :]
- 一列:[:, 1]
- 子区域:[1:3, 1:]
- 子区域:[::3, ::2]
import torch # 导入torch
x = torch.arange(12) # 张量表示一个数值组成的数组,这个数组可能有多个维度
x.shape # 访问张量的形状
x.numel() # 访问张量中元素的总数
X = x.reshape(3, 4) # 改变一个张量的形状而不改变元素数量和元素值
torch.zeros((2, 3, 4)) # 使用全0、全1、其他常量或者从特定分布中随机采样的数字
torch.ones((2, 3, 4))
# 通过提供包含数值的Python列表(或嵌套列表)来为所需张量中的每个元素赋予确定值
torch.tensor([[2, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
# 常见的标准算术运算符(+、-、*、/和**)都可以被升级为按元素运算。
x = torch.tensor([1.0, 2, 4, 8])
y = torch.tensor([2, 2, 2, 2])
x + y, x - y, x * y, x / y, x ** y
torch.exp(x)
# 可以将多个张量连结在一起
X = torch.arange(12, dtype=torch.float32).reshape((3, 4))
Y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
torch.cat((X, Y), dim=0), torch.cat((X, Y), dim=1)
x == y # 通过逻辑运算符构建二元张量
X.sum() # 对张量中的所有元素进行求和会产生一个只有一个元素的张量
# 即使shape不一致,仍然可以通过调用广播机制(broadcasting mechanism)来执行按元素操作
a = torch.arange(3).reshape((3, 1))
b = torch.arange(2).reshape((1, 2))
a + b
X[-1], X[1:3] # 可以用[-1]选择最后一个元素,可以用[1:3]选择第二个和第三个元素
X[1, 2] = 9 # 可以通过指定索引来将元素写入矩阵
X[0:2, :] = 12 # 为多个元素赋值相同的值,只需要索引所有元素,然后为它们赋值
# 运行一些操作可能会导致为新结果分配内存
before = id(Y)
Y = Y + X
id(Y) == before # False
# 执行原地操作
Z = torch.zeros_like(Y)
print('id(Z):', id(Z))
Z[:] = X + Y
print('id(Z):', id(Z)) # 前后一致
# 如果后续计算中,没有重复使用X,也可以使用X[:] = X + Y 或 X += Y 来减少操作的内存开销
before = id(X)
X += Y
id(X) == before # True
# 转换为NumPy张量
A = X.numpy()
B = torch.tensor(A)
type(A), type(B)
# 将大小为1的张量转换为Python标量
a = torch.tensor([3.5])
a, a.item(), float(a), int(a)
2.2 数据预处理
- 创建一个人工数据集,并存储在csv(逗号分隔值)文件。
import os
os.makedirs(os.path.join('..', 'data'), exist_ok=True)
data_file = os.path.join('..', 'data', 'house_tiny.csv')
with open(data_file, 'w') as f:
f.write('NumRooms, Alley, Price\n') # 列名
f.write('NA, Pave, 127500\n') # 每行表示一个数据样本
f.write('2, NA, 106000\n')
f.write('4, NA, 178100\n')
f.write('NA, NA, 140000\n')
- 从创建的csv文件中加载原始数据集
import pandas as pd
data = pd.read_csv(data_file)
print(data)
- 为了处理缺失的数据,典型的方法包括插值和删除
inputs, outputs = data.iloc[:, 0:2], data.iloc[:, 2]
inputs = inputs.fillna(inputs.mean())
print(inputs)
- 对于inputs中的类别值或离散值,将“NaN"视为一个类别
inputs = pd.get_dummies(inputs, dummy_na=True)
print(inputs)
- 将inputs和outputs转换为张量格式
import torch
X, y = torch.tensor(inputs.values), torch.tensor(outputs.values)
2.3 线性代数
- 标量
- 简单操作:
c = a + b c = a ⋅ b c = sin a \begin{aligned} c &= a + b\\c &= a · b\\c &= \sin{a} \end{aligned} ccc=a+b=a⋅b=sina - 长度:
∣ a + b ∣ ≤ ∣ a ∣ + ∣ b ∣ ∣ a ⋅ b ∣ = ∣ a ∣ ⋅ ∣ b ∣ ∣ a ∣ = { a if a > 0 − a otherwise \begin{aligned}&|a + b| \leq |a| + |b|\\&|a · b| = |a| · |b|\\&|a| = \begin{cases}a\quad\quad \text {if a > 0}\\-a\quad \text{otherwise}\end{cases}\end{aligned} ∣a+b∣≤∣a∣+∣b∣∣a⋅b∣=∣a∣⋅∣b∣∣a∣={aif a > 0−aotherwise
- 简单操作:
- 向量
- 简单操作:
c = a + b where c i = a i + b i c = α ⋅ b where c i = α b i c = sin a where c i = sin a i \begin{aligned}&c = a + b\quad\text{where } c_i = a_i + b_i\\&c = \alpha · b\quad\text{where } c_i = {\alpha}b_i\\&c = \sin{a}\quad\text{where } c_i = \sin{a_i}\end{aligned} c=a+bwhere ci=ai+bic=α⋅bwhere ci=αbic=sinawhere ci=sinai - 长度:
∣ ∣ a ∣ ∣ 2 = ( ∑ i = 1 m a i 2 ) 1 / 2 ||a||_2=(\sum_{i=1}^m{a_i^2})^{1/2} ∣∣a∣∣2=(i=1∑mai2)1/2
∣ ∣ a ∣ ∣ ≥ 0 for all a ||a||\geq0\quad \text {for all a} ∣∣a∣∣≥0for all a
∣ ∣ a + b ∣ ∣ ≤ ∣ ∣ a ∣ ∣ + ∣ ∣ b ∣ ∣ ||a+b||\leq||a|| + ||b|| ∣∣a+b∣∣≤∣∣a∣∣+∣∣b∣∣
∣ ∣ a ⋅ b ∣ ∣ = ∣ ∣ a ∣ ∣ ⋅ ∣ ∣ b ∣ ∣ ||a·b||=||a||·||b|| ∣∣a⋅b∣∣=∣∣a∣∣⋅∣∣b∣∣ - 点乘:
a T b = ∑ i a i b i a^Tb=\sum_i{a_ib_i} aTb=i∑aibi - 正交:
a T b = ∑ i a i b i = 0 a^Tb=\sum_i{a_ib_i}=0 aTb=i∑aibi=0
- 简单操作:
- 矩阵
简单操作:
C = A + B where C i j = A i j + B i j C=A+B\quad \text{where } C_{ij}=A_{ij}+B_{ij} C=A+Bwhere Cij=Aij+Bij
C = α ⋅ B where C i j = α B i j C=\alpha·B\quad \text{where } C_{ij}=\alpha B_{ij} C=α⋅Bwhere Cij=αBij
C = sin A where C i j = sin A i j C=\sin A\quad \text{where }C_{ij}=\sin A_{ij} C=sinAwhere Cij=sinAij
乘法(矩阵乘以向量):空间扭曲
c = A b where c i = ∑ j A i j b j c=Ab\quad \text {where } c_i=\sum_j{A_{ij}b_j} c=Abwhere ci=j∑Aijbj
乘法(矩阵乘以矩阵):
c = A B where c i k = ∑ j A i j B j k c=AB\quad \text {where } c_{ik}=\sum_j{A_{ij}B_{jk}} c=ABwhere cik=j∑AijBjk
范数:
c = A ⋅ b h e n c e ∣ ∣ c ∣ ∣ ≤ ∣ ∣ A ∣ ∣ ⋅ ∣ ∣ b ∣ ∣ c = A·b\quad hence\quad ||c||\leq||A||·||b|| c=A⋅bhence∣∣c∣∣≤∣∣A∣∣⋅∣∣b∣∣ 取决于如何衡量b和c的长度
常见范数:矩阵范数:最小的满足的上面公式的值;Frobenius范数: ∣ ∣ A ∣ ∣ F r o b = [ ∑ i j A i j 2 ] 1 / 2 ||A||_{Frob}=[\sum_{ij}A_{ij}^2]^{1/2} ∣∣A∣∣Frob=[ij∑Aij2]1/2- 特殊矩阵:对称和反对称 A i j = A j i a n d A i j = − A j i A_{ij}=A_{ji}\quad and \quad A_{ij}=-A_{ji} Aij=AjiandAij=−Aji
- 特殊矩阵:正定矩阵 ∣ ∣ x ∣ ∣ 2 = x T x ≥ 0 g e n e r a l i z e s t o x T A x ≥ 0 ||x||^2=x^Tx\geq0\quad generalizes\quad to\quad x^TAx\geq0 ∣∣x∣∣2=xTx≥0generalizestoxTAx≥0
- 特殊矩阵:正交矩阵 所有行都互相正交;所有行都有单位长度 U w i t h ∑ j U i j U k j = δ i k U\quad with\quad \sum_j{U_{ij}U_{kj}=\delta_{ik}} Uwithj∑UijUkj=δik;可以写成 U U T = 1 UU^T=1 UUT=1
- 特殊矩阵:置换矩阵
P
w
h
e
r
e
P
i
j
=
1
i
f
a
n
d
o
n
l
y
i
f
j
=
π
(
i
)
P\quad where\quad P_{ij}=1\quad if\quad and\quad only\quad if\quad j=\pi(i)
PwherePij=1ifandonlyifj=π(i) 置换矩阵是正交矩阵
特征向量和特征值: - 不被矩阵改变方向的向量: A x = λ x Ax=\lambda x Ax=λx
- 对称矩阵总是可以找到特征向量
import torch
x = torch.tensor([3.0]) # 标量由只有一个元素的张量表示
y = torch.tensor([2.0])
x + y, x * y, x / y, x ** y
x = torch.arange(4) # 可将向量视为标量值组成的列表 tensor([0, 1, 2, 3])
x[3] # 通过张量的索引来访问任一元素 tensor(3)
len(x) # 访问张量的长度 4
x.shape # 只有一个轴的张量,形状只有一个元素 torch.Size([4])
A = torch.arange(20).reshape(5, 4) #通过指定两个分量m和n来创建一个形状为m*n的矩阵
A.T # 矩阵的转置
B = torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]]) # symmetric matrix
B == B.T
X = torch.arange(24).reshape(2, 3, 4) # 可以构建具有更多轴的数据结构
A = torch.arange(20, dtype=torch.float32).reshape(5, 4)
B = A.clone()
A, A + B
A * B # 两个矩阵的按元素乘法称为 哈达玛积(Hadamard product
a = 2
X = torch.arange(24).reshape(2, 3, 4)
a + X, (a * X).shape
X, X.sum(), X.sum(axis=0), X.sum(axis=1), X.sum(axis=[0, 1])
X.mean(), X.sum() / X.numel()
X.mean(axis=0), X.sum(axis=0) / X.shape[0]
sum_X = X.sum(axis=1, keepdims=True)
X / sum_X # 通过广播将X 除以 sum_X
X.cumsum(axis=0) # 某个轴计算X元素的累积和
y = torch.ones(4, dtype=torch.float32)
x, y, torch.dot(x, y) # 点积
torch.sum(x * y)
A.shape, x.shape, torch.mv(A, x) # 矩阵向量积Ax是一个长度为m的列向量
B = torch.ones(4, 3)
torch.mm(A, B)
# L2范数是向量元素平方和的平方根
u = torch.tensor([3.0, -4.0])
torch.norm(u)
# L1范数是向量元素的绝对值之和
torch.abs(u).sum()
# 矩阵的弗罗贝尼乌斯范数(Frobenius norm)是矩阵元素的平方和的平方根
torch.norm(torch.ones((4, 9)))