PyTorch深度学习实践——6.逻辑sigmoid函数

PyTorch深度学习实践——6.逻辑sigmoid函数

课程链接:《PyTorch深度学习实践》6.逻辑斯蒂回归
虽然叫回归,但是是做分类的
线性回归模型
在这里插入图片描述单样本损失在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在线性空间,我们的估计值y属于一个连续的空间,这种任务叫做回归任务,但是在很多的机器学习任务中,我们要做的是分类
比如ministr数据集,训练集60000个,测试集10000个,有10个分类,我们模型估算出来的结果是一个0…9离散值的集合,我们要估算的是y属于哪一个,这种问题叫做分类问题
然而我们并不是输出输入的样本所属的类别,而是输出它属于每个类别的概率,概率最大的一项作为我们分类的结果

这些都叫sigmoid函数,满足函数值有极限,函数值在(-1,1)之间,都是单调增函数,都是饱和函数,满足这几个条件就叫sigmoid函数,在所有的sigmoid函数中逻辑斯蒂函数最出名,所以现在有些框架里面就直接把逻辑斯蒂函数叫做sigmoid函数,在pytorch里面逻辑斯蒂函数就叫做sigmoid函数
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

逻辑斯蒂回归是做分类用的,输出是概率的分布,在这里插入图片描述
回归与分类的区别:

分类输出y_hat可以是通过的概率(【0,1】),也可以是结果,通过或挂科。
分类输出为概率,在训练时,logistic要把输出值从是实数空间映射到【0,1】在这里插入图片描述
Logstic回归模型:

论文中常把logistic函数写成\sigma(x)在这里插入图片描述在这里插入图片描述

损失函数:

线性回归模型中loss=(y_hat-y)**2在几何上表示两点距离差异

logistic回归模型中,输出是概率的分别,loss要比较概率之间的分布差异,(KL散度,cross-entrpoy交叉熵)

交叉熵举例:

比较D分布和T分布差异性的大小,越大越好在这里插入图片描述在这里插入图片描述
BCE二分类损失函数如上

y是样本真实值,y_hat是预测值,y=1时22,y_hat趋近于一则损失越小,否则越大

mini-batch loss 把BCE加起来求均值即可
linear函数与线性回归函数相同,因此code也相同,因为\sigma里没有参数,也不需要更新,直接在linear后加一个sigmod,最前面加一份functional即可
在这里插入图片描述在这里插入图片描述
损失不同:从原来的MSE编程BCE(binary cross entropy)
在这里插入图片描述

思路:
1、准备数据
2、模型构造
3、损失和优化器
4、循环训练
5、投入模型数据,计算结果
在这里插入图片描述

import torch
import torch.nn.functional as F         # 函数包
import numpy as np
import matplotlib.pyplot as plt


# x,y各有三个数据,每一个数据都只有一个特征,形式为3行一列
x_data = torch.Tensor([[1.0], [2.0], [3.0]]) #构建数据集
											 #注意括号的形式			
y_data = torch.Tensor([[0], [0], [1]])          # 分类数据

class LogisticRegressionModel(torch.nn.Module):   #括号里面表示继承类
												  # 初始化函数和线性回归模型的一样,因为logistic函数中没有新的参数需要初始化
    def __init__(self):                             # 构造函数与线性模型一样,无其他参数
   													#构造函数
        super(LogisticRegressionModel, self).__init__() 
        self.linear = torch.nn.Linear(1, 1)
        										#torch.nn.Linear是pyTorch里面的一个类,加了括号就是实例化对象,包含了权重和偏置两个张量  
        										#可以直接用Linear完成 权重*输入+偏置的计算
       											#Linear也是继承自Module,所以可以自动进行反向传播
       											#nn:Neural Network神经网络
        										#linear是由Linear实例化得到的
 												# (1,1)代表的是输入和输出的特征维度都是一维
                                                # 该层需要学习的参数是w和b,且方式为linear.weight()和linear.bias()
    def forward(self, x):
        y_pred = F.sigmoid(self.linear(x))          # F.sigmoid()
        return y_pred
											 #构造函数用于初始化对象, forward是前馈过程中需要执行的计算,没有backward,这是因为Module构造的对象会根据你的计算图自动实现backward
model = LogisticRegressionModel() #创建一个LogisticRegressioMoel类的实
								  #用模型的时候这样调用,也可以传入参数x,x就送入forward函数,计算出y_pred

criterion = torch.nn.BCELoss(size_average=False) # 用BCE损失函数:cross-entropy(交叉熵),不需要求均值
											  #构造损失函数
 											  #MSELoss需要有y,y_pred,然后构造计算,用MSELoss的共识算出来是一个向量,再把向量求和,最后得出标量的损失值
											  #MSELoss的计算过程也要构建计算图,只要是需要构建计算图,就应该是继承自Module,MSELoss继承自nn.Module
											  #size_average=False表示得到的损失不求均值

#优化器
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
											#BCELoss类参数:size_average=True/False是否求均值、reduction=True/False是否降维
											# model.parameter 自动完成参数的初始化操作
											#优化器不会构建计算图 torch.optim.SGD是一个类,带了参数就是实例化了这个类
											#model.parameters()会检查model里面所有的成员,如果成员里面有相应的权重,就把这些都加到最后训练的参数集合上
											#lr是学习率,当模型比较复杂,pyTorch还支持对模型的不同部分使用不同的学习率,w=w-lr*(损失对权重的导数)


#训练过程
for epoch in range(1000):
    y_pred = model(x_data)  #先在前馈里面算出y_pred
    loss = criterion(y_pred, y_data)  #算损失
   									  # 结合预测值和真实值,最后输出损失值
    print(epoch, loss.item())  #loss是一个对象是标量,打印的时候会自动调用__str__(),不会产生计算图

    optimizer.zero_grad() # 在反向传播之前一定要释放梯
    					  #进行训练的时候梯度归零
    loss.backward() # 反向传播Autograd
    optimizer.step()  # update
    				  #更新,step函数用于更新,会根据所有参数里面所包含的梯度以及预先设置的学习率进行更新

x = np.linspace(0, 10, 200)  #0-10之间平均取200个点
							 # 返回0-10等间距的200个数
x_t = torch.Tensor(x).view((200, 1))        # .view() 转换成矩阵
											# reshape成一个200行1列的矩阵tensor
											#类似于np的reshape
y_t = model(x_t)                        # 将张量送到训练好的模型中,计算结果
										#进行测试
										# 传入模型进行测试
y = y_t.data.numpy()   # 调用numpy将y_t变成n维数组
plt.plot(x, y)


# 图2——这是y=0.5那条横线
plt.plot([0, 10], [0.5, 0.5], c='r')    # 画出y=0.5时的分界线
plt.xlabel('Hours')
plt.ylabel('Probability of Pass')
plt.grid()              # x和y轴的网格线
plt.show()

在这里插入图片描述

输出结果:

 
Epoch =	0	Loss =	2.6060
 
 
Epoch =	100	Loss =	1.9397
 
 
Epoch =	200	Loss =	1.7697
 
 
Epoch =	300	Loss =	1.6271
 
 
Epoch =	400	Loss =	1.5065
 
 
Epoch =	500	Loss =	1.4037
 
 
Epoch =	600	Loss =	1.3155
 
 
Epoch =	700	Loss =	1.2390
 
 
Epoch =	800	Loss =	1.1721
 
 
Epoch =	900	Loss =	1.1133
 
 

在这里插入图片描述
结论:
可以看到大约在2.5小时左右分为两类:
1、小于2.5小时时,结果为0,意为不通过;
2、大于2.5小时时,结果为1,意为通过考试。

torchversion数据集

# mnist数据集,手写数字识别
mnist_train_set = torchvision.datasets.MNIST(root='./dataset/mnist', train=True, download=False)
mnist_test_set = torchvision.datasets.MNIST(root='./dataset/mnist', train=False, download=False)# CIFAR-10数据集——飞机、卡车、猫、鸟等
cifar10_train_set = torchvision.datasets.CIFAR10(root='./dataset/cifar10', train=True, download=True)
cifar10_test_set = torchvision.datasets.CIFAR10(root='./dataset/cifar10', train=False, download=True)
  1. logistic 函数
    (也可以叫sigmoid函数,logistic函数是最典型的sigmoid函数)

将变量映射到0-1之间的数

问题描述:根据输入的学习时间,来预测考试是否合格,最终输出是考试通过的概率。(是一个二分类问题)

概率值用logistic函数值来表示,函数中输入的x是原来的y_pred。

logistic函数图像如图所示,饱和函数—— 导数图像服从正态分布。

sigmoid函数

特点(充分条件)

饱和函数

单调增

有极限

  1. 数据集的改变:因为是二分类问题,y 的取值只能是0或1;在这里插入图片描述

  2. 损失函数的改变:不再使用MSE损失函数,改为使用BCE损失函数,由于PyTorch版本更新,将 size_average=False 更改为 reduction='sum'
    在这里插入图片描述

  3. def __init__没有改变:原因是,\delta (x)(逻辑斯蒂回归函数)是一个没有参数的函数,不需要在构造函数中进行初始化,直接调用就可以;

  4. 模型的改变:由于PyTorch版本更新,不用再导入torch.nn.functional包,可以直接使用包中的Sigmoid函数进行训练,如下图;在这里插入图片描述
    实现线性回归

import torch
# Pytorch实现线性回归

# x,y是矩阵,3行1列 也就是说总共有3个数据,每个数据只有1个特征。
x_data = torch.Tensor([[1.0],[2.0],[3.0]])
y_data = torch.Tensor([[2.0],[4.0],[6.0]])

# Module实现了函数__call__(),call()里面有一条语句是要调用forward()。
# 所以需要重写forward()覆盖掉父类中的forward()。
class LinearModel(torch.nn.Module):
    def __init__(self):
        super(LinearModel, self).__init__()
        # (1,1)是指输入x和输出y的特征维度,这里数据集中的x和y的特征都是1维的。
        self.linear = torch.nn.Linear(1,1)

    def forward(self,x):
        y_pred = self.linear(x)
        return y_pred
model = LinearModel()

criterion = torch.nn.MSELoss(size_average=False) # 不计算平均值。
optimizer = torch.optim.SGD(model.parameters(),lr=0.01)

for epoch in range(1000):
    # forward体现是通过以下语句实现的。
    y_pred = model(x_data)
    loss = criterion(y_pred,y_data)
    print('progress : ',epoch,loss.item())

    optimizer.zero_grad()
    loss.backward()   # 反向传播,计算梯度
    optimizer.step() # 更新w和b的值

print('w = ',model.linear.weight.item())
print('b = ',model.linear.bias.item())

x_test = torch.Tensor([[4.0]])
y_test = model(x_test)
print('y_pred = ',y_test.data)

逻辑斯蒂回归

# 逻辑斯蒂回归

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

# 1. Prepare Dataset
x_data = torch.Tensor([[1.0], [2.0], [3.0]])
y_data = torch.Tensor([[0], [0], [1]])

# 2. Define Model
class LogisticRegressionModel(torch.nn.Module):
    def __init__(self):
        super(LogisticRegressionModel, self).__init__()
        self.linear = torch.nn.Linear(1,1)

    def forward(self,x):
        y_pred = F.sigmoid(self.linear(x))
        return y_pred
model = LogisticRegressionModel()

# 3. Construct Loss and Optimizer
# 默认情况下,loss会基于element平均,如果size_average=False的话,loss会被累加.
criterion = torch.nn.BCELoss(size_average=False)
optimizer = torch.optim.SGD(model.parameters(),lr=0.01)

# 4. Training Cycle
for epoch in range(100):
    y_pred = model(x_data)
    loss = criterion(y_pred,y_data)
    print('progress:', epoch, loss.item())

    optimizer.zero_grad()
    loss.backward()
    optimizer.step()



x = np.linspace(0,10,200)   # 0-10之间取200个点。
x_t = torch.Tensor(x).view((200,1))   # 维度变换
y_t = model(x_t)
y = y_t.data.numpy()
plt.plot(x,y)
# plt.plot([0.10],[0.5,0.5],c='r')
plt.xlabel('Hours')
plt.ylabel('Probability of Pass')
plt.grid()   # 显示网格线 1=True=默认显示;0=False=不显示
plt.show()

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

皮肤小白生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值