6、梯度下降
了解3个定义
导数。偏导数,梯度
梯度下降搜索方法为:
但这种搜索一般是局部最小或者最大值。
影响搜索过程的还有:
初试状态,学习率,动量
激活函数与Loss的梯度
自动求导,autograd.grad
报错:RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
正确代码:
import torch
from torch.nn import functional as F
x = torch.ones(1, requires_grad=True)
w = torch.full([1], 2, requires_grad=True)
mse = F.mse_loss(torch.ones(1), x * w)
torch.autograd.grad(mse, [w])
print(w.requires_grad_())
做分类的话,最后还要用softmax函数, 好处是把原来大的值的比重放的更大
反向传播
一个能够高效计算权重参数的梯度的方法。计算反向传播需要用到高数里的链式法则。
加法节点的反向传播
因为加法节点的反向传播只乘以1,所以输入的值会原封不动地流向下一个节点。
如图:
乘法节点的反向传播
乘法的反向传播会将上游的值乘以正向传播时的输入信号的“翻转值”后传递给下游。
如图:
优化问题
优化问题,有3种要考虑,初始化的值,学习率,优化方法(adam或者SGD)
以函数
z
=
(
x
2
+
y
−
11
)
2
+
(
x
+
y
2
−
7
)
2
z=(x^2+y-11)^2+(x+y^2-7)^2
z=(x2+y−11)2+(x+y2−7)2为例子,利用梯度下降寻找最小值
代码:
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
import torch
def himmelblau(x):
return (x[0] ** 2 + x[1] - 11) ** 2 + (x[0] + x[1] ** 2 - 7) ** 2
x = np.arange(-6, 6, 0.1)
y = np.arange(-6, 6, 0.1)
print("x,y range:", x.shape, y.shape)
# np.meshgrid:生成网格点坐标矩阵
X, Y = np.meshgrid(x, y)
print("X,Y maps:", X.shape, Y.shape)
Z = himmelblau([X, Y])
fig = plt.figure('himmelblau')
# 绘制成3d图
ax = fig.gca(projection='3d')
ax.plot_surface(X, Y, Z)
ax.view_init(60, -30)
ax.set_xlabel('x')
ax.set_ylabel('y')
plt.show()
# 使用随机梯度下降的方法求解
# 初始化x的值为:[1., 0.], [-4, 0.], [4, 0.]
x = torch.tensor([-4., 0.], requires_grad=True)
optimizer = torch.optim.Adam([x], lr=1e-3)
for step in range(20000):
pred = himmelblau(x)
optimizer.zero_grad()
pred.backward()
optimizer.step()
if step % 2000 == 0:
print ('step {}: x = {}, f(x) = {}'
.format(step, x.tolist(), pred.item()))
图片结果为:
运行结果为:
x,y range: (120,) (120,)
X,Y maps: (120, 120) (120, 120)
step 0: x = [-3.999000072479248, -0.0009999999310821295], f(x) = 146.0
step 2000: x = [-3.526559829711914, -2.5002429485321045], f(x) = 19.4503231048584
step 4000: x = [-3.777446746826172, -3.2777843475341797], f(x) = 0.0012130826944485307
step 6000: x = [-3.7793045043945312, -3.283174753189087], f(x) = 5.636138666886836e-09
step 8000: x = [-3.779308319091797, -3.28318190574646], f(x) = 7.248672773130238e-10
step 10000: x = [-3.7793095111846924, -3.28318452835083], f(x) = 8.822098607197404e-11
step 12000: x = [-3.7793102264404297, -3.2831854820251465], f(x) = 8.185452315956354e-12
step 14000: x = [-3.7793102264404297, -3.2831859588623047], f(x) = 0.0
step 16000: x = [-3.7793102264404297, -3.2831859588623047], f(x) = 0.0
step 18000: x = [-3.7793102264404297, -3.2831859588623047], f(x) = 0.0
这里设置的初始值为(-4,0),如果初始值为(0,0)或者(4,0),则最小值虽然都是0,但x和y的值不一样,得出最后结果有4个不同的解对应的最小值0
8、过拟合与欠拟合
过拟合指的是只能拟合训练数据,但不能很好地拟合不包含在训练数据中的其他数据的状态。
机器学习的目标是提高泛化能力,即便是没有包含在训练数据里的未观测数据,也希望模型可以进行正确的识别。
过拟合
发生过拟合的原因,主要有以下两个。
1、模型拥有大量参数、表现力强。
2、训练数据少。
解决方法:
1、权值衰减是一直以来经常被使用的一种抑制过拟合的方法。该方法通过在学习的过程中对大的权重进行惩罚,来抑制过拟合。很多过拟合原本就是因为权重参数取值过大才发生的。
2、Dropout是一种在学习的过程中随机删除神经元的方法。训练时,随机选出隐藏层的神经元,然后将其删除。被删除的神经元不再进行信号的传递。训练时,每传递一次数据,就会随机选择要删除的神经元。然后,测试时,虽然会传递所有的神经元信号,但是对于各个神经元的输出,要乘上训练时的删除比例后再输出。
欠拟合
欠拟合就是模型没有很好地捕捉到数据特征,不能够很好地拟合数据。
解决方法:
1、添加其他特征项,有时是特征不够导致拟合的不好。
2、添加多项式特征,比如给线性模型添加二次或者多次项函数,使模型的泛化能力更强。
3、减少正则化参数,正则化是用来防止过拟合的,但是模型出现欠拟合后,则需要减少正则化参数。
9、交叉验证
在机器学习里,通常来说我们不能将全部用于数据训练模型,否则我们将没有数据集对该模型进行验证,从而评估我们的模型的预测效果。
解决方法:
把整个数据集分成两部分,一部分用于训练,一部分用于验证,这也就是我们经常提到的训练集(training set)和测试集(test set)。
一般采用k折交叉验证,假设k=10,步骤是:
1、将所有数据分成10;
2、不重复地每次取其中一份做测试集,用其他九份做训练集训练模型,之后计算该模型在测试集上的MSE;
3、将10次的MSE取平均,最后得到最终的MSE。
10、正则化
正则化有,L1正则化 和 L2正则化,或者叫作 L1范数 和 L2范数。
L1正则化和L2正则化可以看做是损失函数的惩罚项。所谓『惩罚』是指对损失函数中的某些参数做一些限制。对于线性回归模型,使用L1正则化的模型建叫做Lasso回归,使用L2正则化的模型叫做Ridge回归(岭回归)。
一般回归分析中w表示特征的系数,从上式可以看到正则化项是对系数做了处理(限制)。L1正则化和L2正则化的说明如下:
L1:L1正则化是指权值向量w中各个元素的绝对值之和;
L2:L2正则化是指权值向量w中各个元素的平方和然后再求平方根。
L1正则化和L2正则化的作用:
1、L1正则化可以产生稀疏权值矩阵,即产生一个稀疏模型,可以用于特征选择;
2、L2正则化可以防止模型过拟合(overfitting);一定程度上,L1也可以防止过拟合。