《深度学习从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−1ifx>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+yixi 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=σ(W1x+b1) # h是向量
o
=
w
2
T
h
+
b
2
o = w_2^Th + b_2
o=w2Th+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=σ(W1x+b1)
o
=
W
2
T
h
+
b
2
o = W_2^Th + b_2
o=W2Th+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=σ(W1x+b1)
h
2
=
σ
(
W
2
h
1
+
b
2
)
h_2 = sigma(W_2h_1 + b_2)
h2=σ(W2h1+b2)
h
3
=
σ
(
W
3
h
2
+
b
3
)
h_3 = sigma(W_3h_2 + b_3)
h3=σ(W3h2+b3)
o
=
W
4
h
3
+
b
4
o = W_4h_3 + b_4
o=W4h3+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)=n1i=1∑n21(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
- 计算正则项相对于两个参数的梯度:
∂
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∂JhT+λ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∂JxT+λ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{经验风险}
n1i=1∑nl(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]}
minimizen1i=1∑nβil(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(随机搜索)
随机在超参数空间中搜索几十几百个点,其中就有可能有比较小的值。