目录
1、首先先介绍什么是线性回归与非线性回归?
2、线性回归的目的是什么?
3、用CPU实现线性回归模型
1)初始化x
2)初始化y
3)定义一个模型
4)引用模型
5)指定好参数和损失函数
6)、开始训练
7)、输出训练的结果
4、用GPU实现回归模型
计录自己的学习过程,不喜请勿不要喷,我也有好多不会,不理解。
在统计学中,线性回归是利用称为线性回归方程的最小二乘函数对一个或多个自变量和因变量之间关系进行建模的一种回归分析。这种函数是一个或多个称为回归系数的模型参数的线性组合。当因变量和自变量之间高度相关时,我们就可以使用线性回归来对数据进行预测。
线性回归模型,是利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,运用十分广泛。给出一个线性回归模型,给出x,y,训练出w,b。其表达形式为y = w'x+b,b为误差服从均值为0的正态分布。线性回归模型是利用称为线性回归方程的最小平方函数对一个或多个自变量和因变量之间关系进行建模的一种回归分析。这种函数是一个或多个称为回归系数的模型参数的线性组合。只有一个自变量的情况称为简单回归,大于一个自变量情况的叫做多元回归。
非线性回归,是在掌握大量观察数据的基础上,利用数理统计方法建立因变量与自变量之间的回归关系函数表达式(称回归方程式)。回归分析中,当研究的因果关系只涉及因变量和一个自变量时,叫做一元回归分析;当研究的因果关系涉及因变量和两个或两个以上自变量时,叫做多元回归分析。
区别 线性回归与非线性回归通过自变量的指数来区分
线性回归是研究因变量 y 和自变量 x 之间数量上相互依存的线性关系。在机器学习中自变量 x 为样本特征,因变量 y 为目标值。比如在预测房价的机器学习任务中,每个样本 x 表示与房价有关的各种特征,而 y 为相对应的房屋价格。
import numpy as np
x_values=[i for i in range(11)]#先随便输入一些值
x_train=np.array(x_values,dtype=np.float32)
x_train=x_train.reshape(-1,1)#将数据转化为矩阵格式
x_train.shape
输出
(11, 1)
y_values=[2*i+1 for i in x_values]
y_train=np.array(y_values,dtype=np.float32)
y_train=y_train.reshape(-1,1)
y_train.shape
输出
(11, 1)
import torch
import torch.nn as nn
class LinearRegressionModel(nn.Module):#定义一个类,然后继承nn模块下的一个Module功能
def __init__(self,input_dim,output_dim):#一个线性回归模型,给出x,y,训练出w,b,是的y=wx+b成立
super(LinearRegressionModel,self).__init__()
self.linear=nn.Linear(input_dim,output_dim)#nn.Linear是一个全连接层,因为通常Linear()函数通常用于设置网络中的全连接层。
def forward(self,x):#前向传播
out=self.linear(x)
return out
注意:nn.Linear是调用一个全连接层,因为通常Linear()函数通常用于设置网络中的全连接层。
input_dim=1#因为当时初始化的时候,当时矩阵的大小为(11,1),表示一个特征
output_dim=1#与此同时,输出y对应的也是表示一个特征
model=LinearRegressionModel(input_dim,output_dim)
model
LinearRegressionModel(
(linear): Linear(in_features=1, out_features=1, bias=True)
)
其中:in_features为输入样本的大小(样例特征数),out_features为输出样本的大小(样例特征数),bias默认为true。
epochs=1000#设置训练的次数
learning_rate=0.01#学习率是什么
optimizer=torch.optim.SGD(model.parameters(),lr=learning_rate)#SGD是优化器,优化括号内的参数
criterion=nn.MSELoss()#列出损失函数,分类任务就是交叉墒,回归任务就是MSE常规损失函数
Learning_rate是调整神经网络输入权重的一种方法。如果感知机预测正确,则对应的输入权重不会变化,否则会根据Loss Function来对感知机重新调整,而这个调整的幅度大小就是Learning_rate,也就是在调整的基础上,增加一个比值。这些都比较理论,比较难理解,下面我将通俗的讲解一番;
一般Learning_rate的取值都在0.0001到0.01之间,这个效果就像你走路的步子,步子迈达了,很容易错过最佳点,而迈小了又需要花更长的时间才能到最佳点。所以,直观上来看,在这最好的办法是:先走快一些(大一些的Learning_rate),然后要到最佳点的时候,再降低Learning_rate来到达最佳点。
torch.optim方法优化我们的神经网络,torch.optim 是实现各种优化算法的包。最常用的方法都已经支持,接口很常规,所以以后也可以很容易地集成更复杂的方法。
model.parameters()是获取model网络的参数,构建好神经网络后,网络的参数都保存在parameters()函数当中
for epoch in range(epochs):
epoch+=1#训练一千次
#z注意转化成tensor格式
inputs=torch.from_numpy(x_train)
labels=torch.from_numpy(y_train)
#梯度要清零每一次迭代,如果不清零就会累加
optimizer.zero_grad()
#前向传播
outputs=model(inputs)
#定义损失函数计算损失
loss=criterion(outputs,labels)
#逆向传播
loss.backward()
#更新权重参数,一次训练更新一次参数空间
optimizer.step()
if epoch % 50==0:
print("epoch{}, loss {}".format(epoch,loss.item()))
torch.Tensor是我们之前见过的np.array转化为tensor,但是torch.from_numpy与torch.Tensor有啥区别呢???两者肯定是不一样的,就如同c的int,torch.from_numpy就如同c++的static_cast,我们都知道,如果将int64强制转int32,只要是高位转低位,一定会出现高位被抹去的隐患的,不仅仅可能会丢失精度,甚至会正负对调。这里的torch.Tensor与torch.from_numpy也会存在同样的问题。
当转换的源是float类型,torch.Tensor与torch.from_numpy会共享一块内存!且转换后的结果的类型是torch.float32
当转换的源不是float类型,torch.Tensor得到的是torch.float32,而torch.from_numpy则是与源类型一致!意思就是torch.Tensor只能将源转化为torch.float32。
loss.backward()函数的作用是根据loss来计算网络参数的梯度,其对应的输入默认为网络的叶子节点,即数据集内的数据。
epoch50, loss 8.020606401260011e-11
epoch100, loss 5.078733267271929e-11
epoch150, loss 3.338032975030991e-11
epoch200, loss 1.5593505653388462e-11
epoch250, loss 1.5593505653388462e-11
epoch300, loss 1.5593505653388462e-11
epoch350, loss 1.5593505653388462e-11
epoch400, loss 1.5593505653388462e-11
epoch450, loss 1.5593505653388462e-11
epoch500, loss 1.5593505653388462e-11
epoch550, loss 1.5593505653388462e-11
epoch600, loss 1.5593505653388462e-11
epoch650, loss 1.5593505653388462e-11
epoch700, loss 1.5593505653388462e-11
epoch750, loss 1.5593505653388462e-11
epoch800, loss 1.5593505653388462e-11
epoch850, loss 1.5593505653388462e-11
epoch900, loss 1.5593505653388462e-11
epoch950, loss 1.5593505653388462e-11
epoch1000, loss 1.5593505653388462e-11
可以看出损失值越来越小
predicted=model(torch.from_numpy(x_train).requires_grad_()).data.numpy()#。data.numpy()就是np.array格式
predicted
array([[ 0.99999267],
[ 2.9999938 ],
[ 4.999995 ],
[ 6.9999967 ],
[ 8.999997 ],
[10.999998 ],
[13. ],
[15.000001 ],
[17.000002 ],
[19.000004 ],
[21.000004 ]], dtype=float32)
torch.save(model.state_dict(),'model.pkl')#pkl文件
model.load_state_dict(torch.load('model.pkl'))#读取
只需要将把数据和模型传入cuda(GPU)中就可以了
import torch
import torch.nn as nn
import numpy as np
class LinearRegessionModel(nn.Module):
def __init__(self,input_dim,output_dim):
super(LinearRegressionModel,self).__init__()
self.Linear=nn.Linear(input_dim,output_dim)
def forward(self,x):
out=self.linear(x)
return out
input_dim=1
output_dim=1
model=LinearRegressionModel(input_dim,output_dim)
device=torch.device("cuda:0"if torch.cuda.is_available() else "cpu")#如果GPU配置好了,那就用GPU;否则用CPU
model.to(device)#将模型放入到GPU中去
crierion=nn.MSELoss()
learning_rate=0.01
optimizer=torch.optim.SGD(model.parameters(),lr=learning_rate)
#将数据传入GPU
epochs=1000
for epoch in range(epochs):
epoch+=1
inputs=torch.from_numpy(x_train).to(device)
outputs=torch.from_numpy(y_train).to(device)
optimizer.zero_grad()
outputs=model(inputs)
loss=criterion(outputs,labels)
loss.backward()
optimizer.step()
if epoch %50==0:
print("epoch {},loss {}".format(epoch,loss.item()))
输出:
epoch 50,loss 0.007880532182753086
epoch 100,loss 0.004494754131883383
epoch 150,loss 0.0025636455975472927
epoch 200,loss 0.0014621973969042301
epoch 250,loss 0.0008339814958162606
epoch 300,loss 0.0004756659036502242
epoch 350,loss 0.00027130389935337007
epoch 400,loss 0.00015474861720576882
epoch 450,loss 8.826045814203098e-05
epoch 500,loss 5.033763591200113e-05
epoch 550,loss 2.8714131985907443e-05
epoch 600,loss 1.6377111023757607e-05
epoch 650,loss 9.34002127905842e-06
epoch 700,loss 5.328258339432068e-06
epoch 750,loss 3.0386518119485117e-06
epoch 800,loss 1.7338957150059287e-06
epoch 850,loss 9.889866987577989e-07
epoch 900,loss 5.636979381051788e-07
epoch 950,loss 3.2180872722165077e-07
epoch 1000,loss 1.8340932683713618e-07