PyTorch|逻辑回归的简单实现

01 | 什么是逻辑回归?

经过前面的学习,我们介绍了张量Tensor的基本操作,也知晓了PyTorch的AutoGrad系统。有了上述基础,便可以试着训练简单的机器学习模型了。

今天我们将尝试训练一个简单的逻辑回归模型。

逻辑回归模型(Logistic Regression)是线性的二分类模型,其通用模型表达式如下,其中f(x)被称为sigmoid函数,也称作Logistic函数,由于其具有光滑连续且单调递增,且以“0.5”作为分界点的特性,因此常可用于二分类模型的激活函数。如某样本输入sigmoid函数后其概率大于0.5,则判定为正类,反之判定为负类。

y = f ( W X + b ) f ( x ) = 1 1 + e − x y = f(WX + b) \\ f(x) = \frac{1}{1 +e^{-x}} y=f(WX+b)f(x)=1+ex1

PyTorch|逻辑回归的简单实现_第1张图片
之所以称逻辑回归具有“线性”,是因为sigmoid函数对于(WX+b)进行了“1-1”单调映射,因而对于LR(逻辑回归)函数而言,“y>0.5”也就意味着“WX+b>0”,因此如果去掉sigmoid函数的复合嵌套,发挥分类作用的依旧是“WX+b”,也就是说LR模型本质上是“线性的”。

此外可以对逻辑回归进行诸多变形,如“对数几率回归”,其“几率”定义如下,虽然形式变化,但是本质依旧不变。

几率: y 1 − y 对数几率回归: ln ⁡ y 1 − y = W X + b 几率:\frac{y}{1-y} \\ 对数几率回归:\ln\frac{y}{1-y}=WX + b 几率:1yy对数几率回归:ln1yy=WX+b

02 | 逻辑回归的PyTorch实现

当我们尝试用PyTorch训练机器学习模型时,都遵循着统一的数据流程,即:

  • 数据处理:主要是数据的输入、输出以及预处理工作,同时也包含特征提取与建构

  • 模型搭建:需要基于假定的模型创建叶子结点,并动态创建计算图

  • 损失函数:选择优化目标,如MSE函数

  • 优化器:告诉PyTorch如何更新迭代权值,如梯度下降法

  • 迭代训练:不断重复上述过程,直到损失函数值小于既定阈值(如0.5)

整体的流程如下:

PyTorch|逻辑回归的简单实现_第2张图片
将上述过程在PyCharm中实现,即:

import torch 
import torch.nn as nn 
import matplotlib.pyplot as plt 
import numpy as np 

torch.manual_seed(10) 

# step 1/5 生成训练测试数据 
sample_nums = 100 
mean_value = 1.7 
bias = 1 
n_data = torch.ones(sample_nums, 2) 
x0 = torch.normal(mean_value * n_data, 1) + bias # 类别0,数据shape=(100,2) 
y0 = torch.zeros(sample_nums) # 类别0, 标签shape(100,1) 
x1 = torch.normal(-mean_value * n_data, 1) + bias # 类别1, 数据shape(100,2) 
y1 = torch.ones(sample_nums) # 类别1,标签shape(100,1) 
train_x = torch.cat((x0, x1), 0) # 拼接数据 
train_y = torch.cat((y0, y1), 0) # 拼接标签 

# step 2/5 选择模型 
class LR(nn.Module): # 调用nn.Moudle模块构建LR模型    
		def __init__(self):            
				super(LR, self).__init__()                
				self.features = nn.Linear(2, 1)                
				self.sigmoid = nn.Sigmoid()            
		def forward(self, x): # 确定函数模型                
				x = self.features(x)                    
				x = self.sigmoid(x)                    
				return x 
lr_net = LR()   #实例化LR模型 

# step 3/5 选择损失函数 
loss_fn = nn.BCELoss() # 对于分类问题,推荐采用二分类交叉熵函数 

# step 4/5 选择优化器 
lr = 0.01 #学习率 
optimizer = torch.optim.SGD(lr_net.parameters(), lr=lr, momentum=0.9) 

# step 5/5 模型训练 
for iteration in range(1000):    
		# 前向传播:向模型输入数据,得到输出        
		y_pred = lr_net(train_x)        
		# 计算loss        
		loss = loss_fn(y_pred.squeeze(), train_y)        
		# 反向传播        
		loss.backward()        
		# 更新参数        
		optimizer.step()        
		# 绘图        
		if iteration % 20 == 0:            
				mask = y_pred.ge(0.5).float().squeeze() # 以0.5为阈值进行分类                
				correct = (mask == train_y).sum() # 计算正确预测的样本个数                
				acc = correct.item() / train_y.size(0) # 计算分类准确率                
				plt.scatter(x0.data.numpy()[:, 0], x0.data.numpy()[:, 1], c='r', label='class 0')                
				plt.scatter(x1.data.numpy()[:, 0], x1.data.numpy()[:, 1], c='b', label='class 1')                
				w0, w1 = lr_net.features.weight[0]                
				w0, w1 = float(w0.item()), float(w1.item())                
				plot_b = float(lr_net.features.bias[0].item())                plot_x = np.arange(-6, 6, 0.1)                
				plot_y = (-w0 * plot_x - plot_b) / w1                
				plt.xlim(-5, 7)                
				plt.ylim(-7, 7)                
				plt.plot(plot_x, plot_y)                
				plt.text(-5, 5, 'loss-%.4f' % loss.data.numpy(), fontdict={'size': 20, 'color': "red"})                
				plt.title("iteration:{}\nw0:{:.2f} w1:{:.2f} b:{:.2f} accuracy:{:.2%}".format(iteration, w0, w1, plot_b, acc))                
				plt.legend()                
				plt.show()                
				plt.pause(0.5)          
				if acc > 0.99:                    
						break

03 | 实验迭代过程

下述给出每20次迭代的模型图像,可以看出分类边界逐渐逼近两类样本的真实分界,而这正依赖于多次的模型参数迭代。

PyTorch|逻辑回归的简单实现_第3张图片PyTorch|逻辑回归的简单实现_第4张图片PyTorch|逻辑回归的简单实现_第5张图片
PyTorch|逻辑回归的简单实现_第6张图片PyTorch|逻辑回归的简单实现_第7张图片PyTorch|逻辑回归的简单实现_第8张图片
PyTorch|逻辑回归的简单实现_第9张图片

你可能感兴趣的:(AI+Security,逻辑回归,pytorch)