常见机器学习方法:
线性回归是利用数理统计中回归分析,来确定两种或两种以上的变量间的相互依赖的定量关系的一种统计方法
回归分析中,只包含一个自变量和一个因变量,并且二者的关系可以用一条直线近似表示,这种回归分析称为一元线性回归分析。如包含两个或两个以上的自变量,且自变量与因变量之间是线性关系,则称为多元线性回归
import torch
from torch.nn import Linear, Module, MSELoss
from torch.optim import SGD
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
# 定义一个线性函数, y = 2x + 3
x = np.linspace(0, 20, 500)
y = 3 * x + 5
plt.plot(x, y)
[]
# 生成随机的点,作为训练数据
x = np.random.rand(256)
noise = np.random.randn(256) / 4
y = 3 * x + 5 + noise
df = pd.DataFrame()
df['x'] = x
df['y'] = y
# 显示数据
sns.lmplot(x='x', y='y', data=df)
# 训练
model = Linear(1, 1)
# 参数代表输入输出的特征(features)数量都是1, Linear模型的表达式为y=w*x+b,其中w代表权重,b代表偏置
criterion = MSELoss()
# MSDLoss均方误差
optimizer = SGD(model.parameters(), lr=0.01)
# 优化器选择常见的SGD优化器,即每一次计算batch梯度,学习率0.01
epochs = 2000
# 训练2000次
# 准备训练数据,x_train,y_train的形状(256,1),代表batch大小为256, features为1, astype为float32
x_train = x.reshape(-1, 1).astype('float32')
y_train = y.reshape(-1, 1).astype('float32')
# 开始训练
for i in range(epochs):
# 整理输入和输出符合torch的Tensor类型
inputs = torch.from_numpy(x_train)
labels = torch.from_numpy(y_train)
# 使用模型预测
outputs = model(inputs)
# 重置权重
optimizer.zero_grad()
# 计算损失
loss = criterion(outputs, labels)
# 反向传播
loss.backward()
# 使用优化器默认优化方法
optimizer.step()
if i % 100 == 0:
print('epoch {}, loss: {:.3f}'.format(i, loss.data.item()))
epoch 0, loss: 35.537
epoch 100, loss: 0.294
epoch 200, loss: 0.074
epoch 300, loss: 0.070
epoch 400, loss: 0.068
epoch 500, loss: 0.066
epoch 600, loss: 0.065
epoch 700, loss: 0.064
epoch 800, loss: 0.063
epoch 900, loss: 0.063
epoch 1000, loss: 0.062
epoch 1100, loss: 0.062
epoch 1200, loss: 0.062
epoch 1300, loss: 0.062
epoch 1400, loss: 0.061
epoch 1500, loss: 0.061
epoch 1600, loss: 0.061
epoch 1700, loss: 0.061
epoch 1800, loss: 0.061
epoch 1900, loss: 0.061
# 使用model.parameters提取模型参数,w和b是需要训练的模型参数
[w, b] = model.parameters()
print('w:', w.item(), 'b:', b.item())
w: 3.033578872680664 b: 4.967657089233398
# 可视化模型
predicted = model.forward(torch.from_numpy(x_train)).data.numpy()
plt.plot(x_train, y_train, 'go', label='data', color='red')
plt.plot(x_train, predicted, label='predicted')
plt.legend()
plt.show()
损失函数是用来估量模型的预测值与真实值的差异程度,它是一个非负数,且数值越小则模型性能越好。
训练模型的过程即为通过不断迭代计算,使用梯度下降优化算法,使得损失函数越来越小,以达到模型最优
l o s s ( x , y ) = 1 / n Σ ∣ x i − y i ∣ loss(x,y)=1/n \Sigma|x_{i} - y_{i}| loss(x,y)=1/nΣ∣xi−yi∣
l o s s ( x , c l a s s ) = − x [ c l a s s ] loss(x,class) = -x[class] loss(x,class)=−x[class]
NLLLoss中如果传递了weight参数,会对损失函数进行加权,公式即变成:
l o s s ( x , c l a s s ) = − w e i g h t [ c l a s s ] ∗ x [ c l a s s ] loss(x,class) = -weight[class] * x[class] loss(x,class)=−weight[class]∗x[class]
l o s s ( x , y ) = 1 / n Σ ( x i − y i ) 2 loss(x, y) = 1/n \Sigma (x_i - y_i)^2 loss(x,y)=1/nΣ(xi−yi)2
CrossEntropyLoss() = log_softmax() + NLLLoss()
l o s s s ( x , c l a s s ) = − l o g e x p ( x [ c l a s s ] Σ j e x p ( x [ j ] ) losss(x, class) = -log \cfrac{exp(x[class]} {\Sigma_j exp(x[j])} losss(x,class)=−logΣjexp(x[j])exp(x[class]
因为使用了NLLLoss,所以可以传入weight参数,这时loss的计算公式变为:
l o s s ( x , y ) = w e i g h t s [ c l a s s ] ∗ ( − x [ c l a s s ] + l o g ( Σ j e x p ( x [ j ] ) ) ) loss(x,y)=weights[class] * (-x[class]+log(\Sigma_j exp(x[j]))) loss(x,y)=weights[class]∗(−x[class]+log(Σjexp(x[j])))
所以一般多分类的情况会使用这个损失函数
l o s s ( o , t ) = − 1 n Σ i ( t [ i ] ∗ l o g ( o [ i ] + ( 1 − t [ i ] ) ∗ l o g ( 1 − o [ i ] ) ) loss(o,t)=-\cfrac{1}{n}\Sigma_i(t[i]*log(o[i]+(1-t[i])*log(1-o[i])) loss(o,t)=−n1Σi(t[i]∗log(o[i]+(1−t[i])∗log(1−o[i]))
用的时候需要在该层前面加Sigmoid函数
梯度下降是一个使损失函数越来越小的优化算法,在约束优化问题时,梯度下降(Gradient Descent)是最常采用的方法之一。
梯度的本意是一个向量(矢量),标识某一函数在该点处的方向导数沿着该方向取得最大值,即函数在该点处沿着该方向(此梯度的方向)变化最快,变化率最大(为该梯度的模)
我们需要最小化损失函数,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数和模型参数
对于整个训练集进行梯度下降法的时候,我们必须处理整个训练数据集,然后才能进行梯度下降,即每一步梯度下降法需要对整个训练集进行一次处理,如果训练集很大的时候处理速度会很慢,而且也不可能一次的载入到内存或显存中,所以要把大数据集分成小数据集,一部分一部分的训练,这个训练子集即称为Mini_batch。
对于普通的梯度下降法,一个epoch只能进行一次梯度下降,而对于Mini_batch梯度下降法,一个epoch可以进行Mini_batch的个数次梯度下降
随机梯度下降算法,带有动量(momentum)的算法作为一个可选参数进行设置
optimizer = torch.optim.SGD(model.parameters(), lr=0.1, moment_num=0.9)
RMSprop(root mean square prop)也是一种可以加快梯度下降的算法,利用RMSprop算法,可以减小某些维度更新波动较大的情况,使其梯度下降的变化最快
optimizer = torch.optim.RMSprop(model.parameters(), lr=0.1, alpha=0.99)
Adam优化算法的基本思想就是将Momentnum和RMSprop结合起来的一种适用于不同深度学习结构的优化算法
optimizer = torch.optim.Adam(model.parameters(), lr=0.01, betas=(0.9, 0.99), eps=1e-08)
欠拟合:
过拟合:
# 计算偏差
print(3-w.data.item(), 5-b.data.item())
-0.03357887268066406 0.03234291076660156
利用正则化解决高方差问题,正则化在Cost function中加入正则化项,惩罚模型的复杂度
在损失函数的基础上加上权重参数的绝对值
L = E i n + λ Σ j ∣ w j ∣ L=E_in + \lambda \Sigma_j |w_j| L=Ein+λΣj∣wj∣
在损失函数的基础上加权重参数的平方和
L = E i n + λ Σ j w j 2 L=E_in + \lambda \Sigma_j w_j^2 L=Ein+λΣjwj2
L1比L2更容易获得稀疏解