Logistic回归做分类或预测(实战代码)

1.Logistic回归为什么可以用于分类?

谈这个问题之前,先谈下:一般来说,我们如何用一个模型做分类?

一般的,在机器学习中,使用一个模型做分类的前提,是根据数据(包含样本和标签)训练出一个模型,再用这个训练好的模型做新样本的分类。

比如 x=[1,2,3],y=[2,4,6]. 给出一个x=4,y=?
我们就可以根据现有的数据来训练出一个模型,这里根据数据特点,选用线性回归模型。

这里使用pytorch封装好的线性回归模型,来进行实现

import torch

x_data = torch.tensor([[1.0],[2.0],[3.0]])
y_data = torch.tensor([[2.0],[4.0],[6.0]])


class LinearModel(torch.nn.Module):
    def __init__(self):
        super(LinearModel,self).__init__()
        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):
    y_pred = model(x_data)
    loss = criterion(y_pred,y_data)
    print(epoch,loss.item())
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

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)

结果:
Logistic回归做分类或预测(实战代码)_第1张图片

训练100轮,这个线性模型:y= w*x + b,w=1.999910831451416, b=0.00020285823848098516,当x=4,预测的y值为7.9998

在线性回归模型中,使用的优化器为随机梯度下降SGD.
在求损失时,使用的是MSEloss。MSE在求损失时,求的是所有样本中真实的y与模型预测出的y_pred之间的距离的平方。

Logistic回归做分类或预测(实战代码)_第2张图片
MSE在求线性模型的损失,来评价点估计是合适的。但不能于评价两个概率之间的差异的度量。此时,适用交叉熵。

比如,在分类问题中,给出一个样本,被预测成某类。实际上并不是在输入和输出之间建立直接的关系,给出一个输入,就给出一个具体的输出。而是给出的某类的概率。

举例,在手写数字体识别中,输入的是图片,实际就是一个二维矩阵。有10类类别,分别是:0~9。输出一个图片,输出的并不是0至9中的一个具体数值,而是输出0的可能性,输出1的可能…输出9的可能性。这些可能性相加为1。选概率最大的那个类别作为该图片的类别。
Logistic回归做分类或预测(实战代码)_第3张图片
因此,对于这种求loss损失时,因为是概率,就不能使用MES,而要使用交叉熵。

下面,正式谈Logisitic回归。

Logistic回归其实是基于线性回归的,是在线性回归的基础上加上了logistic函数。下图为logistic函数。Logistic回归与logistic函数不同的是,把函数中的x,换成一个线性函数,即是Logistic回归的公式。
Logistic回归做分类或预测(实战代码)_第4张图片
Logistic回归做分类或预测(实战代码)_第5张图片
但我们在使用Logisitic回归时,要注意其特点。Logistic回归,适用于数字型和标称型数据。同时要求自变量和Logistic概率是线性关系。

标称型:一般在有限的数据中取,而且只存在‘是’和‘否’两种不同的结果(一般用于分类)
数值型:可以在无限的数据中取,而且数值比较具体化,例如4.02,6.23这种值(一般用于回归分析)

Logistic回归做分类或预测(实战代码)_第6张图片
2.Logistic回归做分类(预测)

例子1:
一个人的学习时间,和其通过考试与否存在相关关系。
比如,一个学习时间分别是[1,2,3]小时,其通过考试的结果为[0,0,1]。0表示不通过,1表示通过。此为二分类问题。问一个人学习4小时,能否通过考试?

import torch

# import torch.nn.functional as F

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


# design model using class
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))
        y_pred = torch.sigmoid(self.linear(x))
        return y_pred


model = LogisticRegressionModel()

# 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)

# training cycle forward, backward, update
for epoch in range(1000):
    y_pred = model(x_data)
    loss = criterion(y_pred, y_data)
    print(epoch, loss.item())

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

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)

因其预测结果接近1,故判定能通过考试。
Logistic回归做分类或预测(实战代码)_第7张图片
例2:
用Logistic回归做以下任务。
数据为testSet.csv,如下,共100条训练数据,前两列对应X1,X2的值,第三列是分类0或者1:

testSet.csv
-0.017612 14.053064 0
-1.395634 4.662541 1
-0.752157 6.538620 0
-1.322371 7.152853 0
0.423363 11.054677 0
0.406704 7.067335 1
0.667394 12.741452 0
-2.460150 6.866805 1
0.569411 9.548755 0
-0.026632 10.427743 0
0.850433 6.920334 1
1.347183 13.175500 0
1.176813 3.167020 1
-1.781871 9.097953 0
-0.566606 5.749003 1
0.931635 1.589505 1
-0.024205 6.151823 1
-0.036453 2.690988 1
-0.196949 0.444165 1
1.014459 5.754399 1
1.985298 3.230619 1
-1.693453 -0.557540 1
-0.576525 11.778922 0
-0.346811 -1.678730 1
-2.124484 2.672471 1
1.217916 9.597015 0
-0.733928 9.098687 0
-3.642001 -1.618087 1
0.315985 3.523953 1
1.416614 9.619232 0
-0.386323 3.989286 1
0.556921 8.294984 1
1.224863 11.587360 0
-1.347803 -2.406051 1
1.196604 4.951851 1
0.275221 9.543647 0
0.470575 9.332488 0
-1.889567 9.542662 0
-1.527893 12.150579 0
-1.185247 11.309318 0
-0.445678 3.297303 1
1.042222 6.105155 1
-0.618787 10.320986 0
1.152083 0.548467 1
0.828534 2.676045 1
-1.237728 10.549033 0
-0.683565 -2.166125 1
0.229456 5.921938 1
-0.959885 11.555336 0
0.492911 10.993324 0
0.184992 8.721488 0
-0.355715 10.325976 0
-0.397822 8.058397 0
0.824839 13.730343 0
1.507278 5.027866 1
0.099671 6.835839 1
-0.344008 10.717485 0
1.785928 7.718645 1
-0.918801 11.560217 0
-0.364009 4.747300 1
-0.841722 4.119083 1
0.490426 1.960539 1
-0.007194 9.075792 0
0.356107 12.447863 0
0.342578 12.281162 0
-0.810823 -1.466018 1
2.530777 6.476801 1
1.296683 11.607559 0
0.475487 12.040035 0
-0.783277 11.009725 0
0.074798 11.023650 0
-1.337472 0.468339 1
-0.102781 13.763651 0
-0.147324 2.874846 1
0.518389 9.887035 0
1.015399 7.571882 0
-1.658086 -0.027255 1
1.319944 2.171228 1
2.056216 5.019981 1
-0.851633 4.375691 1
-1.510047 6.061992 0
-1.076637 -3.181888 1
1.821096 10.283990 0
3.010150 8.401766 1
-1.099458 1.688274 1
-0.834872 -1.733869 1
-0.846637 3.849075 1
1.400102 12.628781 0
1.752842 5.468166 1
0.078557 0.059736 1
0.089392 -0.715300 1
1.825662 12.693808 0
0.197445 9.744638 0
0.126117 0.922311 1
-0.679797 1.220530 1
0.677983 2.556666 1
0.761349 10.693862 0
-2.168791 0.143632 1
1.388610 9.341997 0
0.317029 14.739025 0

例三:Logistic回归做糖尿病预测

使用数据集:diabetes

这是一个糖尿病的数据集,主要包括442行数据,10个属性值,分别是:Age(年龄)、性别(Sex)、Body mass index(体质指数)、Average Blood Pressure(平均血压)、S1~S6一年后疾病级数指标。
Target为一年后患疾病的定量指标,值在25到346之间。
Logistic回归做分类或预测(实战代码)_第8张图片

目的: 根据上述10个特征,预测病情发展的量化值。

import torch
from sklearn import datasets, ensemble
import matplotlib.pyplot as plt

# prepare dataset
#从sklearn中加载数据集
diabetes = datasets.load_diabetes()
X, y = diabetes.data, diabetes.target

x_data = torch.Tensor(X)
y_data = torch.Tensor(y)

# design model using class
class LogisticRegressionModel(torch.nn.Module):
    def __init__(self):
        super(LogisticRegressionModel, self).__init__()
        self.linear1 = torch.nn.Linear(10, 8)
        self.linear2 = torch.nn.Linear(8, 4)
        self.linear3 = torch.nn.Linear(4, 1)
        self.softmax = torch.nn.Softmax()

    def forward(self, x):
        x = self.softmax(self.linear1(x))
        x = self.softmax(self.linear2(x))
        x = self.linear3(x)
        x = x.squeeze(-1)  #把N*1展开为1*N
        return x

model = LogisticRegressionModel()

# construct loss and optimizer
# 默认情况下,loss会基于element平均,如果size_average=False的话,loss会被累加。
criterion = torch.nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.001)

# training cycle forward, backward, update

Loss_list = []  #存储每次epoch损失值

for epoch in range(10000):
    y_pred = model(x_data)
    loss = criterion(y_pred, y_data)

    Loss_list.append(loss.item())

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

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


def draw_loss(Loss_list,epoch):
    # 我这里迭代了10000次,所以x的取值范围为(0,10000),然后再将每次相对应的准确率以及损失率附在x上
    plt.cla()
    x1 = range(1, epoch+1)
    y1 = Loss_list
    plt.title('Train loss vs. epoches', fontsize=20)
    plt.plot(x1, y1, '.-')
    plt.xlabel('epoches', fontsize=20)
    plt.ylabel('Train loss', fontsize=20)
    plt.grid()
    plt.savefig("./Train_loss.png")
    plt.show()


x_test = torch.Tensor([[0.03,0.5,0.02,0.05,0.01,0.02,0.07,0.02,0.002,-0.002]])
y_test = model(x_test)
print('y_pred = ', y_test.data)
draw_loss(Loss_list,10000)


预测结果:

在这里插入图片描述
训练时的loss损失:
Logistic回归做分类或预测(实战代码)_第9张图片

需要说明的是,这里不是logistic回归。而是这样一个模型:
Logistic回归做分类或预测(实战代码)_第10张图片
其中Linear层为,对输入的数据做线性变换
Logistic回归做分类或预测(实战代码)_第11张图片

例三:用Logistic回归实现手写数字体识别

你可能感兴趣的:(卷积神经网络,logistic,regression,MNIST,Dataset,手写数字体识别)