学习视频链接:https://www.bilibili.com/video/BV1Y7411d7Ys?t=2680&p=6
1 回归与分类
1.1 回归与分类的区别
名为回归,实则分类。学习逻辑回归时,我们先看看线性回归:线性模型为 y ^ = x ∗ w + b \hat y = x*w+b y^=x∗w+b,其损失函数为 l o s s = ( y ^ − y ) 2 = ( x ⋅ ω − y ) 2 loss = (\hat y -y)^2 = (x\cdot \omega - y)^2 loss=(y^−y)2=(x⋅ω−y)2。我们用数据集来估计的 y ∈ R y \in \mathbb{R} y∈R,这种任务称为回归任务。然而在机器学习任务中,多数则是需要进行分类。分类估算出来的结果是一个集合如 y ∈ 0 , 1 , 2 , 3 , 4 , 5 y \in {0,1,2,3,4,5} y∈0,1,2,3,4,5,估算 y y y是其中的哪一个,即为分类问题。需要注意的是,与回归任务的不同点在于分类问题的结果实则是一个概率,通过分别计算出一个样本属于这些类的所有概率,从中选择出最大的概率为这个样本的一类。
1.2 二分类问题
当分类问题只有两种的时候,称为二分类(0,1)。我们最终计算的 P ( y ^ = 0 ) P(\hat y=0) P(y^=0)和 P ( y ^ = 1 ) P(\hat y=1) P(y^=1)的概率分别是多少,计算它们的分布。对于二分类问题,实际上只需要计算一个值即可,因为两种类的概率和为1作为约束。当 P ( y ^ = 0 ) > P ( y ^ = 1 ) P(\hat y=0) > P(\hat y=1) P(y^=0)>P(y^=1)为0类;当 P ( y ^ = 0 ) < P ( y ^ = 1 ) P(\hat y=0) < P(\hat y=1) P(y^=0)<P(y^=1)为1类;当 P ( y ^ = 0 ) = P ( y ^ = 1 ) P(\hat y=0) = P(\hat y=1) P(y^=0)=P(y^=1),则无法确定分类;当概率趋于 0.5 0.5 0.5时或在一定范围内,通常表示不确定,或者直接给出概率值。
分类问题输出的为一个概率,通过比较概率大小选择出相似概率大的进行分类。
2 实验数据下载(本节未用)
2.1 MNIST Dataset
是一个非常基础的数据集,以前都用于测试学习器的性能指标。在Pytorch中可以直接获取。手写数字的数据库包括:训练集60000例;测试集10000个示例;类别10类。
![](https://i-blog.csdnimg.cn/blog_migrate/d8d1b3324ee8092688b8c434f4d9322e.jpeg)
import torchvision
# 下载训练集,root:表示你需要下载保存的数据集的位置
# train:True表示下载训练集,Flase表示下载测试集;download:自动从网上下载,True表示下载,如果存在则不下载;Flase表示不下载
train_set = torchvision.datasets.MNIST(root="minst",train=True,download=True)
test_set = torchvision.datasets.MNIST(root="minst",train=False,download=True)
2.2 CIFAR-10 Dataset
是32 * 32 的彩色图片数据集。包括了:训练集50000例;测试集10000个示例;10类。
![](https://i-blog.csdnimg.cn/blog_migrate/67a898dbc9fbda0af05dd751f82b76ba.jpeg)
train_set = torchvision.datasets.CIFAR10(root="CIFAR10",train=True,download=True)
test_set = torchvision.datasets.CIFAR10(root="CIFAR10",train=False,download=True)
Files already downloaded and verified
Files already downloaded and verified
3 Sigmoid Function
线性模型: y ^ = w x + b ∈ R \hat y = wx + b \in \mathbb{R} y^=wx+b∈R;线性分类: y ^ ∈ [ 0 , 1 ] \hat y \in [0,1] y^∈[0,1]。因此如果需要将线性模型变为分类即是将其通过一个函数,将其值域变为 [ 0 , 1 ] [0,1] [0,1],这个过程是将实数空间映射到 [ 0 , 1 ] [0,1] [0,1]。
σ ( x ) = 1 1 + e − x σ ′ ( x ) = e − x ( 1 + e − x ) 2 \begin{aligned} \sigma (x) &= \frac{1}{1 + e^{-x}} \\ \sigma ^\prime(x) &= \frac{e^{-x}}{(1 + e^{-x})^2} \end{aligned} σ(x)σ′(x)=1+e−x1=(1+e−x)2e−x
饱和函数图像如下:
import math
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False # 用来正常显示负号
x = np.arange(-20,20,0.1).tolist()
y = [1 / (1 + math.exp(-i)) for i in x]
plt.figure(figsize=(10,6),dpi=300)
plt.plot(x,y,label="原函数")
y = [math.exp(-i)/(math.exp(-i)+1)**2 for i in x]
plt.plot(x,y,label="导数")
plt.legend()
plt.grid()
其它Sigmoid函数性质:函数值有极限,单调函数,饱和函数。最具典型性为 σ ( x ) = 1 1 + e − x \sigma (x) = \frac{1}{1 + e^{-x}} σ(x)=1+e−x1,并将其命名为Sigmoid函数。其它的有 e r f ( π 2 x ) erf(\frac{\sqrt \pi}{2}x) erf(2πx)、 x 1 + x 2 \frac{x}{\sqrt{1+x^2}} 1+x2x、 tanh ( x ) \tanh(x) tanh(x)、 2 π arctan ( π 2 x ) \frac{2}{\pi}\arctan(\frac{\pi}{2}x) π2arctan(2πx)、 2 π g d ( π 2 x ) \frac{2}{\pi}gd(\frac \pi 2 x) π2gd(2πx)、 x 1 + ∣ x ∣ \frac{x}{1+|x|} 1+∣x∣x。
plt.figure(figsize=(10,6),dpi=300)
y = [math.erf(math.pi ** 0.5 / 2 * i) for i in x]
plt.plot(x,y)
y = [i/(1+i**2)**0.5 for i in x]
plt.plot(x,y)
y = [math.tanh(i) for i in x]
plt.plot(x,y)
y = [math.atan(math.pi * i / 2)*2/math.pi for i in x]
plt.plot(x,y)
y = [i/(1+abs(i)) for i in x]
plt.plot(x,y)
plt.grid()
4 Logistic Regression
从线性函数到逻辑回归模型:
![](https://i-blog.csdnimg.cn/blog_migrate/1d9dc682c24dfba94750f119c7718c6b.png)
值域 [ 0 , 1 ] [0,1] [0,1]之间用 σ ( x ) = 1 1 + e − x \sigma (x) = \frac{1}{1 + e^{-x}} σ(x)=1+e−x1,所用均值为0的则使用值域为 [ − 1 , 1 ] [-1,1] [−1,1]的激活函数。
线性回归:预测值与实际值的差值最小化,结果为一个数值
逻辑回归:比较的是两个分布之间的差异(KL散度,cross-entropy(交叉熵)),结果不再是一个数值,而是一个概率分布
交叉熵的计算:其值越大越好。
P D ( x = 1 ) = 0.2 ; P T ( x = 1 ) = 0.3 P D ( x = 2 ) = 0.7 ; P T ( x = 2 ) = 0.4 ⋮ P D ( x = n ) = 0.5 ; P T ( x = n ) = 0.3 \begin{aligned} P_D(x=1) &= 0.2;P_T(x=1)=0.3 \\ P_D(x=2) &= 0.7;P_T(x=2)=0.4 \\ &\vdots \\ P_D(x=n) &= 0.5;P_T(x=n)=0.3 \end{aligned} PD(x=1)PD(x=2)PD(x=n)=0.2;PT(x=1)=0.3=0.7;PT(x=2)=0.4⋮=0.5;PT(x=n)=0.3
c r o s s − e n t r o p y = ∑ i n P D ( x = i ) L n ( P T ( x = i ) ) cross-entropy = \sum \limits_i ^n P_D(x=i)Ln(P_T(x=i)) cross−entropy=i∑nPD(x=i)Ln(PT(x=i))
二分类的交叉熵模型:
![](https://i-blog.csdnimg.cn/blog_migrate/eb2d5617ac0fa4a3483bf76fc44ebc2d.png)
当 y = 1 y=1 y=1时, l o s s = − l o g ( y ^ ) loss=-log(\hat y) loss=−log(y^),此时 y ^ \hat y y^越大损失越小;
当 y = 0 y=0 y=0时, l o s s = − l o g ( 1 − y ^ ) loss=-log(1-\hat y) loss=−log(1−y^),此时 y ^ \hat y y^越小损失越小。
二分类所用的损失函数为BCEloss,小批量数据的损失则求均值。
![](https://i-blog.csdnimg.cn/blog_migrate/372547b4b714e4847ac2fe789d554264.png)
5 逻辑回归(二分类)Pytorch实现
实现思路
![](https://i-blog.csdnimg.cn/blog_migrate/95ef41b64094e574bbbd74367f07ca49.png)
class LogisticRegression(torch.nn.Module):
def __init__(self):
# super是调用父类的构造,这一步是必须有的
# 第一个参数为定义类的名称,第二个为self
super(LogisticRegression,self).__init__()
# 构造一个线性模型对象,其中包含了权重与偏置的初始值,为一个Tensor变量
# Linear是属于Module的,因此只需构建出计算图,即可自动实现前馈与反馈
self.linear = torch.nn.Linear(1,1)
def forward(self,x):
# forward类的重写,原类中存在__call__即可直接调用,前一篇线性回归有说明
y_pred = torch.sigmoid(self.linear(x)) # 调用Sigmoid函数
return y_pred
model = LogisticRegression()
# 构建损失函数
# 二分类交叉熵,同MSELoss作用。求不求均值会影响学习率的取值,其它无影响
criterion = torch.nn.BCELoss(size_average=False)
# 模型优化
optimizer = torch.optim.SGD(model.parameters(),lr=0.01)
C:\Users\17520\Anaconda3\envs\pytorch\lib\site-packages\torch\nn\_reduction.py:43: UserWarning: size_average and reduce args will be deprecated, please use reduction='sum' instead.
warnings.warn(warning.format(ret))
import torch
# Pytorch中的数据等均为Tensor变量
x_data = torch.Tensor([[1],[2],[3]])
y_data = torch.Tensor([[0],[0],[1]]) # 与线性回归不同之处在这里为分类的标签
aa = []
for epoch in range(10000):
y_pred = model(x_data)
loss = criterion(y_pred,y_data)
aa.append(loss.item())
# 所有的梯度归零
optimizer.zero_grad()
# 反馈,方向传播
loss.backward()
# 更新,根据所有参数和学习率来更新
optimizer.step()
x = list(range(10000))
y = aa
plt.figure(figsize=(10,6),dpi=300)
plt.plot(x,y)
plt.xlabel("Epoch")
plt.ylabel("BCELoss")
plt.grid()
plt.show()