《深度学习从0开始》

1.感知机

给定输入x, 权重w, 和偏移 b, 感知机输出:
o = σ ( < w , x > + b ) o = sigma(<w,x> + b) o=σ(<w,x>+b) (<w,x> 表示向量w和x做内积)
σ ( x ) = { 1 i f x > 0 − 1 o t h e r w i s e sigma(x)=left{ begin{matrix} 1 & if x>0 \ -1 & otherwise end{matrix} right. σ(x)={1−1​ifx>0otherwise​
(是个二分类问题)

训练感知机

initialize w=0 and b = 0
repeat #每次拿1个sample来优化
if y i [ < w , x i > + b ] ⩽ 0 y_i[<w,x_i> + b] leqslant 0 yi​[<w,xi​>+b]⩽0 then
w ← w + y i x i w leftarrow w + y_ix_i w←w+yi​xi​ and b ← b + y i b leftarrow b + y_i b←b+yi​
end if
until all classified correctly
等价于使用批量大小为1的梯度下降,并使用如下的损失函数:
l ( y , x , w ) = m a x ( 0 , − y < w , x > ) l(y,x,w) = max(0, -y<w,x>) l(y,x,w)=max(0,−y<w,x>)
感知机不能拟合XOR函数,它只能产生线性分割面导致AI的第一次寒冬

2. 多层感知机:最简单的深度网络

单隐藏层-单分类
输入 x ∈ R n x in R^n x∈Rn
隐藏层 W 1 ∈ R m × n W_1 in R^{m times n} W1​∈Rm×n, b 1 ∈ R m b_1 in R^m b1​∈Rm
输出层 w 2 ∈ R m , b 2 ∈ R w_2 in R^m, b_2 in R w2​∈Rm,b2​∈R
h = σ ( W 1 x + b 1 ) h = sigma(W_1x + b_1) h=σ(W1​x+b1​) # h是向量
o = w 2 T h + b 2 o = w_2^Th + b_2 o=w2T​h+b2​ #o是标量
σ sigma σ 是按元素的激活函数 #激活函数必须是非线性的,否则再多层也是线性模型
常用激活函数:sigmoid[0,1],
Tanh, ReLU(x)=max(x,0)
y 1 , y 2 , . . . y k = s o f t m a x ( o 1 , o 2 , . . . , o k ) y_1, y_2, ...y_k = softmax(o_1,o_2,...,o_k) y1​,y2​,...yk​=softmax(o1​,o2​,...,ok​), 把所有o拉到[0,1]使得加起来=1

-多分类
输入 x ∈ R n x in R^n x∈Rn
隐藏层 W 1 ∈ R m × n , b 1 ∈ R m W_1 in R^{m times n}, b_1 in R^m W1​∈Rm×n,b1​∈Rm
输出层 W 2 ∈ R m × k , b 2 ∈ R k W_2 in R^{m times k}, b_2 in R^k W2​∈Rm×k,b2​∈Rk
h = σ ( W 1 x + b 1 ) h = sigma(W_1x + b_1) h=σ(W1​x+b1​) o = W 2 T h + b 2 o = W_2^Th + b_2 o=W2T​h+b2​
y = s o f t m a x ( o ) y = softmax(o) y=softmax(o) # h、o、y都是向量
多隐藏层
h 1 = σ ( W 1 x + b 1 ) h_1 = sigma(W_1x + b_1) h1​=σ(W1​x+b1​)
h 2 = σ ( W 2 h 1 + b 2 ) h_2 = sigma(W_2h_1 + b_2) h2​=σ(W2​h1​+b2​)
h 3 = σ ( W 3 h 2 + b 3 ) h_3 = sigma(W_3h_2 + b_3) h3​=σ(W3​h2​+b3​)
o = W 4 h 3 + b 4 o = W_4h_3 + b_4 o=W4​h3​+b4​ #o是向量
超参数:隐藏层数、每层隐藏层的大小

总结:
多层感知机使用隐藏层和激活函数来得到非线性模型
常用激活函数是Sigmoid, Tanh, ReLU
使用Softmax 来处理多类分类(包含于nn.crossEntropyLoss中)
超参数:隐藏层层数和层大小
实战代码:D:MLProjects102MLP
#打开visdom: 在【Pytorch】环境下 python -m visdom.server

3.模型选择、欠拟合和过拟合

1)解决训练数据稀缺的方法:
K折交叉验证:原始训练数据被分成K个不重叠的子集。然后进行K次模型训练和验证,每次在K - 1 个子集上进行训练,并在剩余的子集上进行验证。最后,通过对K次实验的结果取平局来估计训练和验证误差。
2)欠拟合和过拟合

  • 训练误差和验证误差都很严重,但它们之间仅有一点差距→欠拟合:可以用更复杂的模型减低训练误差
  • 训练误差明显低于验证误差时 →过拟合:通常更关心验证误差,而不是训练误差和验证误差之间的差距

多项式回归,代码见D:MLProjects104polynomial regression

a.权重衰减=L2正则化

线性函数 f ( x ) = w T x f(x) =w^Tx f(x)=wTx, w 和 x均为向量
线性回归损失:
L ( w , b ) = 1 n ∑ i = 1 n 1 2 ( w T x ( i ) + b − y ( i ) ) 2 L(w,b) = frac{1}{n} sum_{i=1}^{n}frac{1}{2}(w^Tx^{(i)} + b - y^{(i)})^2 L(w,b)=n1​i=1∑n​21​(wTx(i)+b−y(i))2
(w, b)是权重和偏置参数

限制||w||的大小:
||w|| = ||w||_2(L2范数), λ > 0 lambda > 0 λ>0
L ( w , b ) + λ 2 ∣ ∣ w ∣ ∣ 2 L(w,b) + frac{ lambda}{2}||w||^2 L(w,b)+2λ​∣∣w∣∣2
L2正则化回归的小批量随机梯度下降更新如下式:
w ← ( 1 − η λ ) w − η ∣ B ∣ ∑ i ∈ B x ( i ) ( w T x ( i ) + b − y ( i ) ) w leftarrow (1 - eta lambda)w - frac{eta}{|B|}sum_{i in B}x^{(i)}(w^Tx^{(i)} + b - y^{(i)}) w←(1−ηλ)w−∣B∣η​i∈B∑​x(i)(wTx(i)+b−y(i))

较小的 λ lambda λ对应于较小约束的w, 而较大的 λ lambda λ对w的约束更大
权重衰减 代码见D:MLProjects106WeightDecay

b.暂退法(Dropout)

h ′ = { 0 概率为 p h 1 − p 其他情况 h' = left{begin{matrix} 0 & 概率为p \ frac{h}{1-p} & 其他情况 end{matrix}right. h′={01−ph​​概率为p其他情况​
E [ h ′ ] = h E[h'] = h E[h′]=h
Dropout 代码见D:MLProjects107Dropout

4.前向传播、反向传播和计算图

1)前向传播(forward propagation)

前向传播:指的是按顺序(从输入层到输出层)计算和存储神经网络中每层的结果。
单隐藏层的MLP:
(例如Fashion-mnist上的MLP)
假设 x ∈ R d x in R^d x∈Rd, 并且隐藏层不包括偏置项;

中间变量: z = W ( 1 ) x z = W^{(1)}x z=W(1)x , 其中 W ( 1 ) ∈ R h × d W^{(1)} in R^{h times d} W(1)∈Rh×d是隐藏层的权重参数。 z ∈ R h z in R^h z∈Rh

h = ϕ ( z ) h = phi(z) h=ϕ(z);

o = W ( 2 ) h o = W^{(2)}h o=W(2)h, W ( 2 ) ∈ R q × h , o ∈ R q W^{(2)} in R^{q times h}, o in R^q W(2)∈Rq×h,o∈Rq;

假设损失函数为l, 样本标签为y,计算单个数据样本的损失项:

L = l ( o , y ) L = l(o, y) L=l(o,y)

根据 L 2 L_2 L2​正则化的定义, 给定超参数 λ lambda λ, 正则化项为:

s = λ 2 ( ∣ ∣ W ( 1 ) ∣ ∣ F 2 + ∣ ∣ W ( 2 ) ∣ ∣ F 2 ) s = frac{lambda}{2}(||W^{(1)}||_F^2 + ||W^{(2)}||_F^2) s=2λ​(∣∣W(1)∣∣F2​+∣∣W(2)∣∣F2​)
其中矩阵的Frobenius范数是将矩阵展平为向量后应用 L 2 L_2 L2​范数。

模型在给定数据样本上的正则化损失为:

J = L + s J = L+s J=L+s
J J J称为目标函数
前向传播计算图

2)反向传播(backward propagation)

链式法则:
Y = f (X), Z = g(Y)

∂ Z ∂ X = p r o d ( ∂ Z ∂ Y , ∂ Y ∂ X ) frac{partial Z}{partial X} = prod(frac{partial Z}{partial Y},frac{partial Y}{partial X}) ∂X∂Z​=prod(∂Y∂Z​,∂X∂Y​)
prod运算符:执行必要的操作(如换位和交换位置)后将其参数相乘。

目的是计算 ∂ J / ∂ W ( 1 ) partial J / partial W^{(1)} ∂J/∂W(1) 和 ∂ J / ∂ W ( 2 ) partial J / partial W^{(2)} ∂J/∂W(2)

  • 计算目标函数J = L + s相对于损失项L和正则项s的梯度

∂ J ∂ L = 1 , ∂ J ∂ s = 1 frac{partial J}{partial L}=1,frac{partial J}{partial s}=1 ∂L∂J​=1,∂s∂J​=1

  • 根据链式法则计算J关于输出层变量o的梯度:
    ∂ J ∂ o = p r o d ( ∂ J ∂ L , ∂ L ∂ o ) = ∂ L ∂ o ∈ R q frac{partial J}{partial o} = prod(frac{partial J}{partial L},frac{partial L}{partial o}) = frac{partial L}{partial o} in R^q ∂o∂J​=prod(∂L∂J​,∂o∂L​)=∂o∂L​∈Rq
  • 计算正则项相对于两个参数的梯度:

∂ s ∂ W ( 1 ) = λ W ( 1 ) frac{partial s}{partial W^{(1)}} = lambda W^{(1)} ∂W(1)∂s​=λW(1)
∂ s ∂ W ( 2 ) = λ W ( 2 ) frac{partial s}{partial W^{(2)}} = lambda W^{(2)} ∂W(2)∂s​=λW(2)

  • 现在可以计算最接近输出层的模型参数的梯度 ∂ J ∂ W ( 2 ) ∈ R q × h frac{partial J}{partial W^{(2)}} in R^{q times h} ∂W(2)∂J​∈Rq×h.使用链式法则得出:
    ∂ J ∂ W ( 2 ) = p r o d ( ∂ J ∂ o , ∂ o ∂ W ( 2 ) ) + p r o d ( ∂ J ∂ s , ∂ s ∂ W ( 2 ) ) = ∂ J ∂ o h T + λ W ( 2 ) frac{partial J}{partial W^{(2)}}=prod(frac{partial J}{partial o}, frac{partial o}{partial W^{(2)}}) + prod(frac{partial J}{partial s}, frac{partial s}{partial W^{(2)}}) = frac{partial J}{partial o}h^T + lambda W^{(2)} ∂W(2)∂J​=prod(∂o∂J​,∂W(2)∂o​)+prod(∂s∂J​,∂W(2)∂s​)=∂o∂J​hT+λW(2)

  • 为了获得关于 W ( 1 ) W^{(1)} W(1)的梯度,我们需要继续沿着输出层到隐藏层反向传播。关于隐藏层输出的梯度 ∂ J ∂ h ∈ R h frac{partial J}{partial h} in R^h ∂h∂J​∈Rh由下式给出:
    ∂ J ∂ h = p r o d ( ∂ J ∂ o , ∂ o ∂ h ) = W ( 2 ) T ∂ J ∂ o frac{partial J}{partial h} = prod(frac{partial J}{partial o}, frac{partial o}{partial h}) = {W^{(2)}}^Tfrac{partial J}{partial o} ∂h∂J​=prod(∂o∂J​,∂h∂o​)=W(2)T∂o∂J​

  • 由于激活函数 ϕ phi ϕ是按元素计算的,计算中间变量 z z z的梯度 ∂ J / ∂ z ∈ R h partial J/ partial z in R^h ∂J/∂z∈Rh 需要使用按元素乘法运算符,用 ⨀ bigodot ⨀表示:
    ∂ J ∂ z = p r o d ( ∂ J ∂ h , ∂ h ∂ z ) = ∂ J ∂ h ⨀ ϕ ′ ( z ) frac{partial J}{partial z} = prod(frac{partial J}{partial h}, frac{partial h}{partial z}) = frac{partial J}{partial h}bigodotphi'(z) ∂z∂J​=prod(∂h∂J​,∂z∂h​)=∂h∂J​⨀ϕ′(z)

  • 最后得到最接近输入层的模型参数的梯度 ∂ J / ∂ W ( 1 ) ∈ R h × d partial J / partial W^{(1)} in R^{h times d} ∂J/∂W(1)∈Rh×d,根据链式法则,得:
    ∂ J ∂ W ( 1 ) = p r o d ( ∂ J ∂ z , ∂ z ∂ W ( 1 ) ) + p r o d ( ∂ J ∂ s , ∂ s ∂ W ( 1 ) ) = ∂ J ∂ z x T + λ W ( 1 ) frac{partial J}{partial W^{(1)}} = prod(frac{partial J}{partial z},frac{partial z}{partial W^{(1)}}) +prod(frac{partial J}{partial s},frac{partial s}{partial W^{(1)}}) = frac{partial J}{partial z}x^T + lambda W^{(1)} ∂W(1)∂J​=prod(∂z∂J​,∂W(1)∂z​)+prod(∂s∂J​,∂W(1)∂s​)=∂z∂J​xT+λW(1)

梯度消失和梯度爆炸
h ( l ) = f l ( h ( l − 1 ) ) h^{(l)} = f_l(h^{(l-1)}) h(l)=fl​(h(l−1)),因此 o = f L ∘ . . . ∘ f 1 ( x ) o= f_L circ...circ f_1(x) o=fL​∘...∘f1​(x).
o关于任何一组参数 W ( l ) W^{(l)} W(l)的梯度写为下式:
∂ W ( l ) o = ∂ h ( L − 1 ) h ( L ) . . . ∂ h ( l ) h ( l + 1 ) ∂ w ( l ) h ( l ) partial _{W^{(l)}}o = partial_{h^{(L-1)}}h^{(L)}...partial_{h^{(l)}}h^{(l+1)}partial_{w^{(l)}}h^{(l)} ∂W(l)​o=∂h(L−1)​h(L)...∂h(l)​h(l+1)∂w(l)​h(l)
换言之,该梯度是L-1个矩阵 M ( L ) . . . M ( l + 1 ) M^{(L)}... M^{(l + 1)} M(L)...M(l+1) 与梯度向量 v ( l ) v^{(l)} v(l)的乘积
代码实现见D:MLProjects109gradient vanish,explode

5.环境和分布偏移

通过将基于模型的决策引入环境,我们可能会破坏模型。
条件概率:
P ( A ∣ B ) = P ( A B ) P ( B ) P(A|B) = frac{P(AB)}{P(B)} P(A∣B)=P(B)P(AB)​
“A在B发生的条件下”发生的概率 P ( A ∣ B ) P(A|B) P(A∣B)
A,B同时发生的概率,联合概率 P ( A B ) = P ( A , B ) = P ( A ∩ B ) P(AB)=P(A,B)=P(Acap B) P(AB)=P(A,B)=P(A∩B)

1)协变量偏移
假设:虽然输入的分布可能随时间而改变,但标签函数(条件分布P(y|x))没有改变,称之为协变量偏移(covariate shift)
2)标签偏移(label shift)
假设标签边缘概率P(y)可以改变,但类别条件分布P(x|y)在不同的领域之间保持不变。
3)概念偏移(concept shift)

分布偏移纠正:

经验风险与实际风险

训练数据 { ( x 1 , y 1 ) , . . . , ( x n , y n ) } {(x_1,y_1), ...,(x_n, y_n)} {(x1​,y1​),...,(xn​,yn​)},在每一个小批量之后更新模型f的参数(不考虑正则化):

最小化
1 n ∑ i = 1 n l ( f ( x i ) , y i ) (经验风险) frac{1}{n}sum_{i=1}^nl(f(x_i), y_i) tag{经验风险} n1​i=1∑n​l(f(xi​),yi​)(经验风险)

经验风险是为了近似真实风险
整个训练数据上的平均损失,即从其真实分布p(x,y)中抽取的所有数据的总体损失的期望值:
E p ( x , y ) [ l ( f ( x ) , y ) ] = ∬ l ( f ( x ) , y ) p ( x , y ) d x d y (真实风险) E_{p(x,y)}[l(f(x),y)] = iint l(f(x),y)p(x,y) dxdy tag{真实风险} Ep(x,y)​[l(f(x),y)]=∬l(f(x),y)p(x,y)dxdy(真实风险)

协变量偏移纠正

m i n i m i z e 1 n ∑ i = 1 n β i l ( f ( x i ) , y i ) ([1]) minimize frac{1}{n}sum_{i=1}^nbeta_il(f(x_i),y_i) tag{[1]} minimizen1​i=1∑n​βi​l(f(xi​),yi​)([1])
完整协变量偏移纠正算法:
假设我们有一个训练集 { ( x i , y 1 ) , . . . , ( x n , y n ) } {(x_i,y_1),...,(x_n,y_n)} {(xi​,y1​),...,(xn​,yn​)} 和一个未标记的测试集
{ u 1 , . . . , u m } {u_1, ...,u_m} {u1​,...,um​}。对于协变量偏移,我们假设1<= i <=n的 x i x_i xi​来自某个源分布, u i u_i ui​来自目标分布。
1.生成一个二元分类训练集: { ( x 1 , − 1 ) , . . . , ( x n , − 1 ) , ( u 1 , 1 ) , . . . , ( u m , 1 ) } {(x_1, -1), ..., (x_n,-1), (u_1,1),...,( u_m, 1)} {(x1​,−1),...,(xn​,−1),(u1​,1),...,(um​,1)}
2.用对数几率回归训练二元分类器得到函数h。
3.使用 β i = e x p ( h ( x i ) ) beta_i = exp(h(x_i)) βi​=exp(h(xi​))或更好的 β i = m i n ( e x p ( h ( x i ) ) , c ) beta_i =min(exp(h(x_i)),c) βi​=min(exp(h(xi​)),c)(c为常量)对训练数据进行加权。
4.使用权重 β i beta_i βi​进行([1])中 { ( x i , y 1 ) , . . . , ( x n , y n ) } {(x_i,y_1),...,(x_n,y_n)} {(xi​,y1​),...,(xn​,yn​)}的训练。

标签偏移纠正

假设处理k个类别的分类任务。q,p分别是源分布(训练时的分布)和目标分布(测试时的分布)。假设标签的分布随时间变化: q ( y ) ≠ p ( y ) q(y) neq p(y) q(y)=p(y), 但类别条件分布保持不变 q ( x ∣ y ) = p ( x ∣ y ) q(x|y) = p(x|y) q(x∣y)=p(x∣y)。
如果源分布q(y)是“错误的”, 可以根据真实风险恒等式进行更正:
∬ l ( f ( x ) , y ) p ( x ∣ y ) p ( y ) d x d y = ∬ l ( f ( x ) , y ) q ( x ∣ y ) q ( y ) p ( y ) q ( y ) d x d y iint l(f(x),y)p(x|y)p(y)dxdy = iint l(f(x),y)q(x|y)q(y)frac{p(y)}{q(y)}dxdy ∬l(f(x),y)p(x∣y)p(y)dxdy=∬l(f(x),y)q(x∣y)q(y)q(y)p(y)​dxdy
重要性权重将对于于标签似然比率:
β i = p ( y i ) q ( y i ) beta_i = frac{p(y_i)}{q(y_i)} βi​=q(yi​)p(yi​)​
1.采用现成发分类器(基于训练数据训练的)并使用验证集(也来自训练分布)计算其混淆矩阵C:k × times × k 矩阵,列对于于标签类别,行对于于模型的预测类别,每个单元格的值 c i j c_{ij} cij​是验证集中,真实标签为j,而模型预测为i的样本数量所占的比例。
2.所有模型在测试时的预测取平均数,得到平均模型输出 μ ( y ^ ) ∈ R k mu (hat y) in R^k μ(y^​)∈Rk
3. p ( y ) = C − 1 μ ( y ^ ) p(y) = C^{-1}mu (hat y) p(y)=C−1μ(y^​)
4.观测源数据上的标签,很容易计算估计分布q(y)。
5.计算权重 β i beta_i βi​,并将其代入([1])中。

概念偏移纠正
eg.由于环境的磨损,交通摄像头的箭头会逐渐退化,影响摄像头的图像质量;
新闻内容逐渐变化(即新新闻的出现)。
使用新数据更新现有的网络权重,而不是从头开始训练。

学习问题的分类:
1)批量学习:batch learning
2)在线学习 online learning:
m o d e l : f t → d a t a : x t → e s t i m a t e : f t ( x t ) → o b s e r v a t i o n : y t model: f_t →data: x_t →estimate: f_t(x_t) →observation: y_t model:ft​→data:xt​→estimate:ft​(xt​)→observation:yt​ → l o s s : l ( y t , f t ( x t ) ) loss :l(y_t,f_t(x_t)) loss:l(yt​,ft​(xt​)) → m o d e l : f t + 1 model: f_{t+1} model:ft+1​
在这个循环中,给定新的观测结果,我们会不断改进我们的模型。
3)老虎机bandits
4)控制
5)强化学习 reinforcement learning

Kaggle 房价预测:代码见D:MLProjects116HousePricePrediction
K折交叉验证与超参数搜索
为什么K折交叉验证:1.数据量小,单一的把数据都用来训练模型,容易导致过拟合;小数据集的交叉验证,建议选择较大的k值。
2. 降低模型方差,从而提高模型的泛化能力。
超参数选择:1.Grid SearchCV(网格搜索)
GridSearch + CV: 网格搜索和交叉验证
网格搜索:搜索的是参数。即在指定的参数范围内,按步长依次调整参数,利用调整的参数训练学习器,从所有的参数中找到在验证集上精度最高的参数。
Grid Search: 一种调参手段;穷举搜索:在所有候选的参数选择中,通过循环遍历,尝试每一种可能性,表现最好的参数就是最终的结果。其原理就像在数组里找打最大值。缺点:耗时!
网格搜索适合适用于三、四个(或更少)的超参数
2. RandomizedSearchCV(随机搜索)
随机在超参数空间中搜索几十几百个点,其中就有可能有比较小的值。