Linear Regression、Logistic Regression、激励函数activation function(relu,sigmoid, tanh, softplus)
1.5.2.Linear Regression
1.5.2.1.Linear Regression
1.5.2.1.1.案例1
1.5.2.1.2.案例2
1.5.2.1.3.案例3源码(带有保存模型)
1.5.2.2.Logistic Regression
1.5.2.2.1.案例1
1.5.2.2.2.更深更宽的网络
1.5.2.2.3.逻辑回归案例
1.5.2.3.Classification
1.5.2.4.激励函数activation function(relu,sigmoid, tanh, softplus)
1.5.2.Linear Regression
以下转自:
https://blog.csdn.net/caichao08/article/details/78993893 https://blog.csdn.net/weixin_42587745/article/details/90346126 https://ptorch.com/news/6.html https://www.jb51.net/article/140557.htm1.5.2.1.Linear Regression
对于线性回归,即给出一系列的点,找一条直线,使得这条直线与这些点的距离之和最小。
上图就简单地描绘出了线性回归的基本原理,接下来我们来重点讲讲如何用pytorch写一个简单的线性回归。
接下来,使用torch.from_numpy()和numpy函数即可进行相互转换:
x = torch.from_numpy(x) y = torch.from_numpy(y)1.5.2.1.1.案例1
使用PyTorch定义线性回归模型一般分以下几步:
1.设计网络架构
2.构建损失函数(loss)和优化器(optimizer)
3.训练(包括前馈(forward)、反向传播(backward)、更新模型参数(update))
迭代十次打印结果:
0 次循环: 128.36353 1 次循环: 57.22348 2 次循环: 25.55281 3 次循环: 11.452799 4 次循环: 5.1747613 5 次循环: 2.3788614 6 次循环: 1.1331253 7 次循环: 0.57749355 8 次循环: 0.32909214 9 次循环: 0.2174757loss还在继续下降,此时输入4得到的结果还不是预测的很准 当迭代次数设置为50时:10 次循环: 0.16676745 11 次循环: 0.14318845 12 次循环: 0.13170049 13 次循环: 0.12560984 14 次循环: 0.12193605 15 次循环: 0.11935152 16 次循环: 0.117265806 17 次循环: 0.11541578 18 次循环: 0.11368369 19 次循环: 0.11201717 20 次循环: 0.11039279 21 次循环: 0.108799875 22 次循环: 0.10723348 23 次循环: 0.105691046 24 次循环: 0.10417137 25 次循环: 0.10267406 26 次循环: 0.10119824 27 次循环: 0.09974393 28 次循环: 0.09831043 29 次循环: 0.0968976 30 次循环: 0.09550497 31 次循环: 0.09413239 32 次循环: 0.09277948 33 次循环: 0.09144618 34 次循环: 0.0901321 35 次循环: 0.08883653 36 次循环: 0.08755979 37 次循环: 0.08630159 38 次循环: 0.085061245 39 次循环: 0.08383879 40 次循环: 0.082633875 41 次循环: 0.08144614 42 次循环: 0.08027585 43 次循环: 0.07912208 44 次循环: 0.07798502 45 次循环: 0.07686419 46 次循环: 0.07575947 47 次循环: 0.07467067 48 次循环: 0.073597685 49 次循环: 0.07253992 predict (after training) 4 [[7.690391]]此时,函数已经拟合比较好了
torch.nn.Linear(1,1),只需要知道输入和输出维度,里面的参数矩阵是随机初始化的(具体是不是随机的还是按照一定约束条件初始化的我不确定),所有每次计算loss会下降到不同的位置(模型的参数更新从而也不同),导致结果不一样。
1.5.2.1.2.案例2
以下转自:https://blog.csdn.net/caichao08/article/details/78993893
首先第一步是产生训练的数据,这里我们采用scikit工具箱来完成。
# -*- coding: UTF-8 -*-import numpy as np import matplotlib.pyplot as plt from sklearn.datasets.samples_generator import make_regression import torch import torch.nn as nn from torch.autograd import Variable# n_samples表示样本数量, n_features表示输入参数个数, noise代表噪声, coef选择是否输出系数 # 当n_features = 1 时,可以进行可视化 X, y, coef =make_regression(n_samples=1000, n_features=1,noise=10, coef=True) plt.scatter(X, y, color='green') plt.plot(X, X*coef, color='red',linewidth=3) plt.xticks(()) plt.yticks(()) plt.show()print(coef) print(np.shape(X)) print(np.shape(y))输出结果:
84.20925934904598 (1000, 1) (1000,)下一步是建立一个模型
# 首先将数据转换成tensor变量 # 上面的make_regression产生的是double型数据, 直接导入到tensor里面会跑不通, 这里把它们转成float32型的变量 X = X.astype('float32') y = y.astype('float32')print(np.size(X)) print(np.shape(X)) print(np.shape(y))# 下面的这一步非常的关键, pytorch里面只支持(n, 1)这种类型的matric,而不支持这种(n,)类似的scaler或vector类型的变量 y = np.reshape(y, (np.size(X), 1)) # 下面是将numpy转换成Tensor,使用torch.from_numpy()和numpy函数即可进行相互转换 train_x = torch.from_numpy(X) train_y = torch.from_numpy(y)# 再定义一个模型,一般用类的形式来产生 # 这里的nn.Module是被继承了,nn.Module里面包含了很多需要的模块 class linear_regression(nn.Module):"""linear regression module"""def __init__(self):super(linear_regression, self).__init__()# 定义Linear 函数只有一个输入一个输出,这里的nn.Linear表示的是 y=w*x+b,里面的两个参数都是1,表示的是x是1维,y也是1维。self.linear = nn.Linear(1, 1)def forward(self, x):out = self.linear(x)return outmodel = linear_regression() print(model) print(train_x.size()) print(train_y.size()) print(type(train_x))输出结果:
1000 (1000, 1) (1000,) linear_regression((linear): Linear(in_features=1, out_features=1, bias=True) ) torch.Size([1000, 1]) torch.Size([1000, 1]) <class 'torch.Tensor'>接着对模型的未知参数进行求解
# 紧接着需要定义loss和optimize了 # 利用最小二乘来定义损失 # 学习率,当学习率很小的时候,得循环很多次才能得到比较好的结果,如果是le-3,下面的num_epoch得1900次差不多才能得到比较好的效果 learning_rate = 1e-2 # 这里使用的是最小二乘loss,之后我们做分类问题更多的使用的是cross entropy loss,交叉熵。优化函数使用的是随机梯度下降,注意需要将model的参数model.parameters()传进去让这个函数知道他要优化的参数是哪些。 criterion = nn.MSELoss() optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)# SGD的第一参数传入的是模型要优化的参数, 第二个表示的是学习率 # 开始训练 num_epoch = 200for epoch in range(num_epoch):# 将数据转换成tensor变量,这样可以自动求导inputs = Variable(train_x)targets = Variable(train_y)# # 前向 + 后向 + 优化optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, targets)loss.backward()optimizer.step()if (epoch+1) % 20 == 0:print("loss:" + {loss.item()})#print(f'Epoch[{epoch+1}/{num_epochs}], loss: {loss.item():.6f}')只要learning_rate选的好,这里基本上一步就能得出正确结果了
再看看预测的结果
# 下面来用数据做预测 # 特别注意的是需要用model.eval(),让model变成测试模式,这主要是对dropout和batch, normalization的操作在训练和测试的时候是不一样的。 model.eval() # model只支持tensor类型的变量, 所以对model的输入要进行转换, 而画图则要转化成numpy类型 predicts = model(Variable(train_x)).data.numpy() plt.figure() plt.plot(X, y, 'go', label=u'original data') plt.plot(X, coef*X, 'b', label=u'ground truth') plt.plot(X, predicts, 'r', label=u'predicted data') plt.legend() plt.show()从下面的结果图上来看还是很准的
1.5.2.1.3.案例3源码(带有保存模型)
# -*- coding: UTF-8 -*-import matplotlib.pyplot as plt import numpy as np import torch from torch import nn from torch.autograd import Variablex_train = np.array([[3.3], [4.4], [5.5], [6.71], [6.93], [4.168],[9.779], [6.182], [7.59], [2.167], [7.042],[10.791], [5.313], [7.997], [3.1]], dtype=np.float32)y_train = np.array([[1.7], [2.76], [2.09], [3.19], [1.694], [1.573],[3.366], [2.596], [2.53], [1.221], [2.827],[3.465], [1.65], [2.904], [1.3]], dtype=np.float32)x_train = torch.from_numpy(x_train)y_train = torch.from_numpy(y_train)# Linear Regression Model class linearRegression(nn.Module):def __init__(self):super(linearRegression, self).__init__()self.linear = nn.Linear(1, 1) # input and output is 1 dimensiondef forward(self, x):out = self.linear(x)return outmodel = linearRegression() # 定义loss和优化函数 criterion = nn.MSELoss() optimizer = torch.optim.SGD(model.parameters(), lr=1e-4)# 开始训练 num_epochs = 2000 for epoch in range(num_epochs):inputs = x_traintarget = y_train# forwardout = model(inputs)loss = criterion(out, target)# backwardoptimizer.zero_grad()loss.backward()optimizer.step()if (epoch+1) % 20 == 0:print(f'Epoch[{epoch+1}/{num_epochs}], loss: {loss.item():.6f}')model.eval() with torch.no_grad():predict = model(x_train) predict = predict.data.numpy()fig = plt.figure(figsize=(10, 5)) plt.plot(x_train.numpy(), y_train.numpy(), 'ro', label='Original data') plt.plot(x_train.numpy(), predict, label='Fitting Line') # 显示图例 plt.legend() plt.show()# 保存模型 torch.save(model.state_dict(), './linear.pth')运行结果:
Epoch[20/2000], loss: 16.022251 Epoch[40/2000], loss: 11.373667 Epoch[60/2000], loss: 8.088304 Epoch[80/2000], loss: 5.766390 Epoch[100/2000], loss: 4.125387 Epoch[120/2000], loss: 2.965617 Epoch[140/2000], loss: 2.145954 Epoch[160/2000], loss: 1.566661 Epoch[180/2000], loss: 1.157250 Epoch[200/2000], loss: 0.867900 Epoch[220/2000], loss: 0.663402 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Epoch[1960/2000], loss: 0.170428 Epoch[1980/2000], loss: 0.170426 Epoch[2000/2000], loss: 0.1704251.5.2.2.Logistic Regression
以下参考:https://www.jb51.net/article/140557.htm
http://blog.csdn.net/m0_37306360
线性回归是解决回归问题的,逻辑回归和线性回归很像,但是它是解决分类问题的(一般二分类问题:0 or 1)。也可以多分类问题(用softmax可以实现)。
使用pytorch实现逻辑回归的基本过程和线性回归差不多,但是有以下几个区别:
以下为sigmoid函数:
在逻辑回归中,我们预测如果当输出大于0.5时,y=1;否则y=0。
损失函数一般采用交叉熵loss:
1.5.2.2.1.案例1
import torch from torch.autograd import Variablex_data = Variable(torch.Tensor([[0.6], [1.0], [3.5], [4.0]])) y_data = Variable(torch.Tensor([[0.], [0.], [1.], [1.]]))class Model(torch.nn.Module):def __init__(self):super(Model, self).__init__()self.linear = torch.nn.Linear(1, 1) # One in one outself.sigmoid = torch.nn.Sigmoid()def forward(self, x):y_pred = self.sigmoid(self.linear(x))return y_pred# Our model model = Model()# Construct loss function and optimizer criterion = torch.nn.BCELoss() optimizer = torch.optim.SGD(model.parameters(), lr=0.01)# Training loop for epoch in range(500):# Forward passy_pred = model(x_data)# Compute lossloss = criterion(y_pred, y_data)if epoch % 20 == 0:print(loss.data.numpy())# Zero gradientsoptimizer.zero_grad()# Backward passloss.backward()# update weightsoptimizer.step()# After training hour_var = Variable(torch.Tensor([[0.5]])) print("predict (after training)", 0.5, model.forward(hour_var).data[0][0]) hour_var = Variable(torch.Tensor([[7.0]])) print("predict (after training)", 7.0, model.forward(hour_var).data[0][0])输出结果为:
2.1419365 1.5513724 1.0856804 0.7997792 0.6584054 0.59043765 0.55404615 0.53147745 0.5154158 0.50267094 0.49175227 0.4819196 0.47278577 0.46413925 0.4558599 0.44787702 0.44014725 0.432643 0.4253458 0.41824245 0.4113233 0.4045803 0.3980071 0.3915978 0.38534725 predict (after training) 0.5 tensor(0.4064) predict (after training) 7.0 tensor(0.9840)训练完模型之后,输入新的数据0.5,此时输出小于0.5,则为0类别,输入7输出大于0.5,则为1类别。使用softmax做多分类时,哪个维度的数值大,则为哪个数值所对应位置的类别。
1.5.2.2.2.更深更宽的网络
前面的例子都是浅层输入为一维的网络,如果需要更深更宽的网络,使用pytorch也可以很好的实现,以逻辑回归为例:
当输入x的维度很大时,需要更宽的网络:
更深的网络:
采用下面数据集(下载地址:https://github.com/hunkim/PyTorchZeroToAll/tree/master/data)
输入维度为八:
结果:
(Before training) tensor([[0.3952]]) 0 0.78095376 50 0.7321978 100 0.7009846 150 0.68111795 200 0.668492 250 0.66046023 300 0.6553401 350 0.65206724 400 0.6499692 xxxxxxxxxxxxxxxxxxx 1550 0.6460486 1600 0.6460425 1650 0.64603657 1700 0.6460306 1750 0.64602476 1800 0.6460189 1850 0.6460131 1900 0.6460073 1950 0.6460014 predict (after training) [[0.6534828]]1.5.2.2.3.逻辑回归案例:
# -*- coding: UTF-8 -*-import timeimport torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets, transforms# 定义超参数 batch_size = 64 learning_rate = 1e-3 num_epochs = 100# 下载训练集 MNIST 手写数字训练集 train_dataset = datasets.FashionMNIST(root='../datasets', train=True, transform=transforms.ToTensor(), download=True)test_dataset = datasets.FashionMNIST(root='../datasets', train=False, transform=transforms.ToTensor())train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)# 定义 Logistic Regression 模型 class Logistic_Regression(nn.Module):def __init__(self, in_dim, n_class):super(Logistic_Regression, self).__init__()self.logistic = nn.Linear(in_dim, n_class)def forward(self, x):out = self.logistic(x)return outmodel = Logistic_Regression(28 * 28, 10) # 图片大小是28x28 use_gpu = torch.cuda.is_available() # 判断是否有GPU加速 if use_gpu:model = model.cuda() # 定义loss和optimizer criterion = nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)# 开始训练 for epoch in range(num_epochs):print('*' * 10)print(f'epoch {epoch + 1}')since = time.time()running_loss = 0.0running_acc = 0.0model.train()for i, data in enumerate(train_loader, 1):img, label = dataimg = img.view(img.size(0), -1) # 将图片展开成 28x28if use_gpu:img = img.cuda()label = label.cuda()# 向前传播out = model(img)loss = criterion(out, label)running_loss += loss.item()_, pred = torch.max(out, 1)running_acc += (pred == label).float().mean()# 向后传播optimizer.zero_grad()loss.backward()optimizer.step()if i % 300 == 0:print(f'[{epoch + 1}/{num_epochs}] Loss: {running_loss / i:.6f}, Acc: {running_acc / i:.6f}')print(f'Finish {epoch + 1} epoch, Loss: {running_loss / i:.6f}, Acc: {running_acc / i:.6f}')model.eval()eval_loss = 0.eval_acc = 0.for data in test_loader:img, label = dataimg = img.view(img.size(0), -1)if use_gpu:img = img.cuda()label = label.cuda()with torch.no_grad():out = model(img)loss = criterion(out, label)eval_loss += loss.item()_, pred = torch.max(out, 1)eval_acc += (pred == label).float().mean()print(f'Test Loss: {eval_loss / len(test_loader):.6f}, Acc: {eval_acc / len(test_loader):.6f}')print(f'Time:{(time.time() - since):.1f} s')# 保存模型 torch.save(model.state_dict(), './logstic.pth')1.5.2.3.Classification
以下参考:https://www.jb51.net/article/139098.htm
1.5.2.4.激励函数activation function
以下参考:https://www.jb51.net/article/139098.htm
Torch的激励函数都在torch.nn.functional中,relu,sigmoid, tanh, softplus都是常用的激励函数。
相关代码:
# -*- coding: UTF-8 -*-import torch import torch.nn.functional as F from torch.autograd import Variable import matplotlib.pyplot as pltx = torch.linspace(-5, 5, 200) x_variable = Variable(x) # 将x放入Variable x_np = x_variable.data.numpy()# 经过4种不同的激励函数得到的numpy形式的数据结果 y_relu = F.relu(x_variable).data.numpy() y_sigmoid = torch.sigmoid(x_variable).data.numpy() y_tanh = torch.tanh(x_variable).data.numpy() y_softplus = F.softplus(x_variable).data.numpy()plt.figure(1, figsize=(8, 6))plt.subplot(221) plt.plot(x_np, y_relu, c='red', label='relu') plt.ylim((-1, 5)) plt.legend(loc='best')plt.subplot(222) plt.plot(x_np, y_sigmoid, c='red', label='sigmoid') plt.ylim((-0.2, 1.2)) plt.legend(loc='best')plt.subplot(223) plt.plot(x_np, y_tanh, c='red', label='tanh') plt.ylim((-1.2, 1.2)) plt.legend(loc='best')plt.subplot(224) plt.plot(x_np, y_softplus, c='red', label='softplus') plt.ylim((-0.2, 6)) plt.legend(loc='best')plt.show()输出结果:
总结
以上是生活随笔为你收集整理的Linear Regression、Logistic Regression、激励函数activation function(relu,sigmoid, tanh, softplus)的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 79式70毫米微型反坦克火箭
- 下一篇: 06_Flink命令行界面、作业管理示例