机器学习之LinearRegression与Logistic Regression逻辑斯蒂回归(三)

时间:2021-09-08 23:53:50

一 评价尺度

sklearn包含四种评价尺度

1 均方差(mean-squared-error)

2 平均绝对值误差(mean_absolute_error)

3 可释方差得分(explained_variance_score)

4 中值绝对误差(Median absolute error)

5 R2 决定系数(拟合优度)

  • 模型越好:r2→1
  • 模型越差:r2→0

二 逻辑斯蒂回归

1 概述

在逻辑斯蒂回归中,我们将会采用sigmoid函数作为激励函数,所以它被称为sigmoid回归或对数几率回归(logistic regression),需要注意的是,虽然带有回归,但事实上它并不是一种回归算法,而是一种分类算法。

优点:

1 它是直接对分类的可能性进行建模的,无需事先假设数据分布,这样就避免了假设分布不准确所带来的问题

2 其针对于分类的可能性进行建模的,所以它不仅能预测出类别,还可以得到属于该类别的概率

3 实现简单,易于理解和实现;计算代价不高,速度很快,存储资源低

4 数据量大就用逻辑斯蒂 数据量小,特征多,用SVM knn

缺点:

容易欠拟合,分类精度可能不高

线性回归与逻辑回归的区别

线性回归: 线性回归用来做回归预测,解决回归问题

根据几组已知数据和拟合函数训练其中未知参数,使得拟合损失达到最小。然后用所得拟合函数进行预测。

逻辑回归: 逻辑回归用于做二分类 , 解决分类问题

和拟合函数训练其中未知参数 , 使得对数似然函数最大。然后用所得的拟合函数进行二分类。

线性回归 逻辑回归
目的 预测 分类
未知 {0,1}
函数 拟合函数 预测函数
参数计算方式 最小二乘 最大似然估计

注意:

1 预测函数其实就是拟合函数做了一个逻辑函数的转换

2 最大似然估计是计算使得数据出现的可能性最大的参数,依仗的自然是Probability。而最小二乘是计算误差损失。因此两者不可混淆

(2) 本质的区分

  • 逻辑回归就是对线性回归做了一个压缩,将y 的值从y∈(+∞,−∞)压缩到(0,1)。为什么简单的压缩就能将回归问题变成分类问题?

  • 从数据说起,线性回归的样本的输出,都是连续值,y∈(+∞,−∞)而,逻辑回归中y∈{0,1},只能取0和1。对于拟合函数也有本质上的差别:

\[ 逻辑回归:f(x)=p(y=1∣x;θ)=g(θTX) \]

\[ 线性回归:f(x)=θTX=θ1x1+θ2x2+⋯+θnxn \]

​ 线性回归拟合函数,的确是对f(x)的输出变量y的拟合,而逻辑回归的拟合函数是对为1类的样本概率拟合。

  • 为什么采用1类的样本概率进行拟合,这里就要谈到logstic函数的本质

    若要直接通过回归的方法去预测二分类问题, y 到底是0类还是1类,最好的函数是单位阶跃函数。然而单位阶跃函数不连续(GLM 的必要条件),而 logsitic 函数恰好接近于单位阶跃函数,且单调可微。于是希望通过该复合函数去拟合分类问题,产生:

机器学习之LinearRegression与Logistic Regression逻辑斯蒂回归(三)

  • 于是,θTX=0就相当于是1类和0类的决策边界:

  • \[ 当θTX>0,则有y>0.5;若θTX→+∞ ,则y→1 ,即y 为1类; \]

  • \[ 当θTX<0,则有y<0.5 ; 若θTX→−∞,则y→0,即 y 为0类。 \]

    这个时候就能看出区别来了,在线性回归中θTXθTX为预测值的拟合函数;而在逻辑回归中θTX=0为决策边界

    ​因此利用Logistics回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,以此进行分类。

机器学习之LinearRegression与Logistic Regression逻辑斯蒂回归(三)

三 Logistic Regression实战练习

实例: 手写数字分类

import numpy as np
import pandas as pd
from pandas import Series,DataFrame
import matplotlib.pyplot as plt
%matplotlib inline

# LogisticRegression虽然是线性回归模型,但是只能处理分类问题
# 概率模型,使用概率进行分类
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier

# 加载手写数字集
from sklearn import datasets
digits = datasets.load_digits()    #

#输出  {'data': array([[ 0.,  0.,  5., ...,  0.,  0.,  0.],
        [ 0.,  0.,  0., ..., 10.,  0.,  0.],
        [ 0.,  0.,  0., ..., 16.,  9.,  0.],
        ...,
        [ 0.,  0.,  1., ...,  6.,  0.,  0.],
        [ 0.,  0.,  2., ..., 12.,  0.,  0.],
        [ 0.,  0., 10., ..., 12.,  1.,  0.]]),
 'target': array([0, 1, 2, ..., 8, 9, 8]),
 'target_names': array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]),
 'images': array([[[ 0.,  0.,  5., ...,  1.,  0.,  0.],
         [ 0.,  0., 13., ..., 15.,  5.,  0.],
                   ....
data = digits.data    #(1797, 64)  表示1797条,一维64的矩阵
images = digits.images   #(1797, 8, 8)  表示1797条,8*8的二维矩阵
display(data.shape,images.shape)

plt.imshow(images[0],cmap='gray')
plt.imshow(data[0].reshape((8,8)),cmap='gray')  #将64一维转成8*8的二维矩阵实际都是表示一组数据

机器学习之LinearRegression与Logistic Regression逻辑斯蒂回归(三)

# 对数据集进行拆分,得到训练集和测试集
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(data,target,test_size=0.2,random_state=1)

#采用逻辑斯蒂回归模型与KNN
logistic = LogisticRegression()
knn = KNeighborsClassifier(n_neighbors=5)

#对knn与逻辑斯蒂进行训练
logistic.fit(X_train,y_train)
y1_ = logistic.predict(X_test)
knn.fit(X_train,y_train)
y2_ = knn.predict(X_test)

查看模型评分

# 分类模型可以查看准确率来对模型进行评价
# 直接用算法模型调用score方法来实现
logistic.score(X_test,y_test)  
knn.score(X_test,y_test)

#输出  0.9694444444444444
      0.9944444444444445
# 模型在测试集上评分特别高,但是在真实环境下准确率却很低,这叫病态
# 引起这种现象的原因,主要是算法训练的过度拟合

分类展示

# 展示分类的成果
# 取测试集的前100个数据
plt.figure(figsize=(12,16))
for i in range(100):
    axes = plt.subplot(10,10,i+1)
    img = X_test[i].reshape((8,8))
    axes.imshow(img,cmap='gray')
    axes.axis('off')
    true = y_test[i]
    knn_r = y2_[i]
    logistic_r = y1_[i]
    title = 'T:'+str(true)+'\nK:'+str(knn_r) + ' L:'+str(logistic_r)
    axes.set_title(title)

机器学习之LinearRegression与Logistic Regression逻辑斯蒂回归(三)

# 对logistic函数进行调参,查看参数对结果的影响
# 超参 函数级别 knn n_neibors logistic pentily C
# 模型参数 f(x) = wx+b

logistic = LogisticRegression(C=0.5,penalty='l1')
logistic.fit(X_train,y_train)
logistic.score(X_test,y_test)
#0.975

人脸的自动补全

导包

import numpy as np
import pandas as pd
from pandas import Series,DataFrame
from sklearn.datasets import fetch_olivetti_faces
import matplotlib.pyplot as plt
%matplotlib inline

提取数据

faces = fetch_olivetti_faces()
data = faces.data
images = faces.images
target = faces.target

拆分测试训练集

from sklearn.linear_model import LinearRegression,Ridge,Lasso
from sklearn.neighbors import KNeighborsRegressor
# 拆分训练集和测试集
from sklearn.model_selection import train_test_split

# 每个人拿出9张照片做训练数据,拿出1张照片做测试数据
# 样本特征采用上半边脸,样本标签采用下半边脸
def train_test_split_face(data,test_size):
    X_train = []
    X_test = []
    y_train = []
    y_test = []
    for i in range(40):
        for j in range(10):
            face = data[i*10+j]
            up_face = face[:2048]
            bottom_face = face[2048:]
            if j < (1-test_size)*10:
                # 保存为训练数据
                X_train.append(up_face)
                y_train.append(bottom_face)
            else:
                # 保存为测试数据
                X_test.append(up_face) 
                y_test.append(bottom_face)
    return np.array(X_train),np.array(X_test),np.array(y_train),np.array(y_test)
#训练集与测试集
X_train,X_test,y_train,y_test = train_test_split_face(data,test_size=0.1)
#拆分出的上下半边脸
plt.imshow(X_train[0].reshape((32,64)),cmap='gray')
plt.imshow(y_train[0].reshape((32,64)),cmap='gray')

训练模型

knn = KNeighborsRegressor()
linear = LinearRegression()
ridge = Ridge()
lasso = Lasso()

knn.fit(X_train,y_train)
linear.fit(X_train,y_train)
ridge.fit(X_train,y_train)
lasso.fit(X_train,y_train)

预测数据

# 预测所有数据
knn_y_ = knn.predict(X_test)
linear_y_ = linear.predict(X_test)
ridge_y_ = ridge.predict(X_test)
lasso_y_ = lasso.predict(X_test)


plt.figure(figsize=(10,4))

true_up_face = X_test[0]
true_bottom_face = y_test[0]
pre_bottom_face = knn_y_[0]
axes1 = plt.subplot(1,2,1)
true_face = np.concatenate((true_up_face,true_bottom_face))
axes1.imshow(true_face.reshape((64,64)),cmap='gray')
axes1.set_title('True')

axes2 = plt.subplot(1,2,2)
pre_face = np.concatenate((true_up_face,pre_bottom_face))
axes2.imshow(pre_face.reshape((64,64)),cmap='gray')
axes2.set_title('Predict')

results = np.array([knn_y_,ridge_y_,lasso_y_,linear_y_])
titles = np.array(['KNN','RIDGE','LASSO','LINEAR'])


plt.figure(figsize=(16,18))
for i in range(5):
    true_up_face = X_test[i]
    true_bottom_face = y_test[i]
    true_face = np.concatenate((true_up_face,true_bottom_face)).reshape((64,64))
    axes = plt.subplot(5,5,i*5+1)
    axes.imshow(true_face,cmap='gray')
    axes.set_title('True')
    for index,y_ in enumerate(results):
        axes = plt.subplot(5,5,i*5+1+index+1)
        pre_bottom_face = y_[index]
        pre_face = np.concatenate((true_up_face,pre_bottom_face)).reshape((64,64))
        axes.imshow(pre_face,cmap='gray')
        axes.set_title(titles[index])

数据量较少,仅为测试使用

机器学习之LinearRegression与Logistic Regression逻辑斯蒂回归(三)