简单来说, 逻辑回归(Logistic Regression)是一种用于解决分类问题的机器学习方法,用于估计某种事物的可能性。由于逻辑回归的原理是用逻辑函数把线性回归的结果yyy
映射到(0,1),故先介绍线性回归函数。
线性回归函数的数学表达式:
其中xix_ixi
是自变量,yyy
是因变量,yyy
的值域为(-∞,+∞),θ0\theta_0θ0
是常数项,θiθ_iθi
(i=1,2,...,n)是待求系数,不同的权重θiθ_iθi
反映了自变量对因变量不同的贡献程度。
由sigmoid的图像可知,当x趋于无穷,y趋于1,当x趋于负无穷,y趋于0
前文中提到过逻辑回归的原理是用逻辑函数把线性回归的结果从(-∞,+∞)映射到(0,1)。我们用公式描述上面这句话:
把线性回归函数的结果yyy
,放到sigmod函数中去,就构造了二类逻辑回归函数。由yyy
的值域和sigmod函数的值域知,在逻辑回归函数中用sigmod函数把线性回归的结果yyy
映射到(0,1),得到的这个结果类似一个概率值。如果现在把逻辑回归中的结果g(y)g(y)g(y)
看成某个事件发生的概率,那么这个事件不发生的概率就是1−g(y)1-g(y)1−g(y)
。
举个例子,如果我们把车贷中违约客户(未按期还款)的样本标签定义为1,即y=1y=1y=1
,正常客户(按时还款)的样本标签定义为0,即y=0y=0y=0
,那么我们就可以通过逻辑回归函数预测客户违约或者不违约的可能性:(以下式子为预测违约的可能性)
1.4.1 极大似然函数
结合以上例子,如果我们积累了大量违约客户和正常客户的样本数据,即很多组(x,y)(x,y)(x,y)
,那么我们就可以推测逻辑回归函数中的参数θθθ
的大概值。而当我们知道θθθ
的值,那我们就可以用这个逻辑回归函数来预测新客户的违约的可能性。
如果令上文中提到的违约概率:
那么违约的概率可以写成:
不违约的概率可以写成:
对于某一个客户,我们采集到了样本数据(x,y)(x,y)(x,y)
。对于这个样本,他的标签是yyy
的概率可以定义成:
其中y∈0,1y∈{0,1}y∈0,1
。当y=0y=0y=0
时,上式为不违约的概率,当y=1y=1y=1
时,上式为违约的概率。
现在,假设我们有mmm
个客户的观测样本:
将每一个样本发生的概率相乘,就是这个合成在一起得到的合事件发生的总概率L(θ)L(θ)L(θ)
,即极大似然函数,可以写成:
,其中θθθ
为待求参数
注:如果L(θ)L(θ)L(θ)
的值越接近1说明什么?说明我们其中每一个预测概率越接近1,也就是说明我们每一次的预测越准。因此我们要求一个能让L(θ)L(θ)L(θ)
尽量大的参数θθθ
。
为便于求解,我们引入不改变函数单调性的对数函数ln,把连乘变成加法,得到以下对数似然函数:
这里我们要让L(θ)L(θ)L(θ)
尽可能大,也就是 −ln(L(θ))- ln(L(θ))−ln(L(θ))
尽可能小。
1.4.2 构造损失函数
在机器学习中,我们知道损失函数一般定义为预测值和真实值的差,如果损失函数越小,说明模型预测越准。结合上文中逻辑回归中的极大似然函数,如果取整个数据集上的平均对数似然损失,我们就可以得到以下式子:
其中J(θ)J(θ)J(θ)
为损失函数,由对数似然函数前面添加负号取平均得到。
softmax函数数学表达式:
,kkk
为类别数,jjj
代表第几类
用softmax函数把线性回归的结果从(-∞,+∞)映射到(0,1)。在多分类中,函数的输入是从kkk
个不同的线性函数得到的结果,而样本向量 xxx
属于第j(j
个分类的概率为:
举个例子,比如在一个4分类问题中(kkk
=4),一个xxx
经过4个不同线性函数得到四个yyy
,分别为:
那么xxx
属于这4个类的其中一个类的概率分别为:
且以上各个概率之和为1
现在我们同样有mmm
个观测样本,类别数为kkk
。
我们先通过softmax函数求出每一个XiX_iXi
在各个类别上的概率,并选择出与YiY_iYi
相等的那个分类上的概率。与二类逻辑回归类似,我们把选择出来的这些概率相乘。得到如下公式:
同样的,L(W)L(W)L(W)
越大,也就说明我们预测的越准,因此我们需要找一组合适的WWW
使得我们的L(W)L(W)L(W)
尽可能的大。
为便于求解,我们同样引入不改变函数单调性的对数函数ln,把连乘变成加法,得到对数似然函数:
这里我们要让L(W)L(W)L(W)
尽可能大,也就是−ln(L(W))-ln(L(W))−ln(L(W))
尽可能小。
损失函数越小,说明模型预测越准。结合上文中的极大似然函数,如果取整个数据集上的平均对数似然损失,我们就可以得到以下式子:
其中$$J(W)$$为损失函数,由对数似然函数前面添加负号取平均得到。
在这个实例中我们的数据集为60000张图片,且每张图片都带有一个[0,9]的整数数字。测试集为10000张图片,同样的每张图片都带有一个[0,9]的整数数字。由此可知本题中类别数为10,类别为0,1,2,3,4,5,6,7,8,9。以下展示代码和演示。
import torch
import torch.nn as nn
import torchvision.transforms as transforms
import torchvision.datasets as dsets
train_dataset = dsets.MNIST(root=‘./data’,
train=True,
transform=transforms.ToTensor(),
download=True)
test_dataset = dsets.MNIST(root=‘./data’,
train=False,
transform=transforms.ToTensor())Copy
以上导入训练集train_dataset和测试集test_dataset 。两个数据集中的元素均为元组,元组的第一个元素为一张图片的数据,第二个元素为图片中表示的整数数字。
batch_size = 100
n_iters = 3000
num_epochs = n_iters / (len(train_dataset) / batch_size)
num_epochs = int(num_epochs)
Copy
batch_size表示每次取用的图片张数,n_iters表示训练模型的次数,num_epochs代表对整个训练集遍历的次数
train_loader = torch.utils.data.DataLoader(dataset=train_dataset,
batch_size=batch_size,
shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=test_dataset,
batch_size=batch_size,
shuffle=False)
Copy
相当于创建一个容器,这个容器每次弹出batch_size个数据
class LogisticRegressionModel(nn.Module):
def __init__(self, input_dim, output_dim):
super(LogisticRegressionModel, self).__init__()
self.linear = nn.Linear(input_dim, output_dim)
def forward(self, x):
out = self.linear(x)
return out
构建模型,在_init_中定义数据,在forward中执行计算。
input_dim = 28*28 #输入数据应当为[batch_size,input_dim] ,28X28代表图片像素宽高
output_dim = 10 #输出数据应当为[batch_size,output_dim]
model = LogisticRegressionModel(input_dim, output_dim)
Copy
criterion = nn.CrossEntropyLoss() #下文介绍
learning_rate = 0.001 #超参数 ,可自己设定
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) '''采用随机梯度下降方法更新参数。'''
Copy
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
images = images.view(-1, 28*28) #改变images形状
labels = labels
outputs = model(images) #这里最后调用的是类中的foward函数
loss = criterion(outputs, labels) #求损失
optimizer.zero_grad() #梯度清零
loss.backward() #求参数梯度
optimizer.step() #更新参数
Copy
在这里我们具体演示训练数据中的一次循环:
在这次循环中,我们先从train_loader中取出一组images(也就前面提到的x),和一组与images对应的labels(也就是前面提到的y)。这里的images包含100(batch_size的值)张图片的数据,labels是对应的每张图片里的正确数字。
这组images经过转化后,size 变为 100X784;labels的size为100,如下:
接着,我们把images放入模型中,会得到一组outpus。注意:最初时,模型在计算images时,用的时一组模型自己生成的随机参数
再把outputs和labels放入到criterion函数中求loss。根据之前的公式介绍,在 criterion(outputs,labels) 函数中实际执行了三步操作:
第一步:用softmax 把outputs的每个数转化成概率,得到S:
第二步:从S的每一行中,选取一个概率。但这里的选取,不是随机选取,而是根据labels的每个元素值进行选取,选取后的结果记为P。如下图:
第三步:我们可以知道,从第二步中选取出来的P就是模型预测的每张图片在正确类上的可能性。接着我们把P中的每个元素进行连乘,就得到我们前面说过的似然函数,再求loss:
求得了Loss,我们再根据Loss更新参数。由于这里使用的是随机梯度下降法,我们用loss.backward()函数求当前参数的梯度(求梯度前使用optimizer.zero_grad()进行梯度清零)。下一次model要用的新的参数为:
经过若干次这样的循环之后,loss将会变得更小,模型中参数也将变得更优。
iter = 0
for epoch in range(num_epochs):
for i, (images, labels) in enumerate(train_loader):
images = images.view(-1, 28*28)
labels = labels
outputs = model(images)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
#上面的代码已经演示过了,而下面的代码则是,每训练一定次数,检测准确率
if iter % 500 == 0:
correct = 0
total = 0
for images, labels in test_loader:
images = images.view(-1, 28 * 28).requires_grad_()
outputs = model(images)
_, predicted = torch.max(outputs.data, 1) '''outputs每行中的元素值大的,表明x是这个类的概率越大'''
total += labels.size(0)
correct += (predicted == labels).sum()
accuracy = 100 * correct / total
print('Iteration: {}. Loss: {}. Accuracy: {}'.format(iter, loss.item(), accuracy))
逻辑回归(logistics regression)原理-让你彻底读懂逻辑回归 https://cloud.tencent.com/developer/article/1694338
Logistic Regression https://www.deeplearningwizard.com/deep_learning/practical_pytorch/pytorch_logistic_regression/