09-LinearRegression线性回归和逻辑斯蒂回归

一.导数

  • 几种常见函数的导数

① C'=0(C为常数);
② (xn)'=nx(n-1) (n∈Q);
③ (sinx)'=cosx;
④ (cosx)'=-sinx;
⑤ (ex)'=ex;
⑥ (ax)'=axIna (ln为自然对数)
⑦ loga(x)'=(1/x)loga(e)

  • 导数的四则运算

①(u±v)'=u'±v'
②(uv)'=u'v+uv'
③(u/v)'=(u'v-uv')/ v^2
④[u(v)]'=[u'(v)]*v' (u(v)为复合函数f[g(x)])

二.线性回归

  • 最小二乘法


    二乘法1.png

    二乘法2.png
二乘法2.1.png

二乘法2.2.png
  • 线性
得名于f(x)=ax+b的图像的形象 很直观 就是一条直线的形象
  • 原理图


    线性原理图.png
实例糖尿病线性回归

1.导入相应包

import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets
from sklearn.linear_model import LinearRegression

2.读取文件数据

diabetes = datasets.load_diabetes() #糖尿病的信息

3.处理数据

#获取索引是2的数据
diabetes_X = diabetes.data[:,np.newaxis,2]

diabetes_X_train = diabetes_X[:-20]
diabetes_X_test = diabetes_X[-20:]

diabetes_Y = diabetes.target

diabetes_Y_train = diabetes_Y[:-20]
diabetes_Y_test = diabetes_Y[-20:]

4.训练线性回归算法

regr = LinearRegression()

# 第1步:训练
regr.fit(diabetes_X_train,diabetes_Y_train)

5.预测数据并绘制

plt.scatter(diabetes_X_test,diabetes_Y_test,color = 'black')

plt.plot(diabetes_X_test,regr.predict(diabetes_X_test),color = 'blue',lw = 3)

plt.show()
糖尿病.png

三.矩阵

  • 满秩矩阵

满秩矩阵(non-singular matrix): 设A是n阶矩阵, 若r(A) = n, 则称A为满秩矩阵。但满秩不局限于n阶矩阵。若矩阵秩等于行数,称为行满秩;若矩阵秩等于列数,称为列满秩。既是行满秩又是列满秩则为n阶矩阵即n阶方阵。行满秩矩阵就是行向量线性无关,列满秩矩阵就是列向量线性无关;所以如果是方阵,行满秩矩阵与列满秩矩阵是等价的。
满秩有行满秩和列满秩,既是行满秩又是列满秩的话就一定是是方阵

  • 奇异矩阵

奇异矩阵是线性代数的概念,就是该矩阵的秩不是满秩。首先,看这个矩阵是不是方阵(即行数和列数相等的矩阵。若行数和列数不相等,那就谈不上奇异矩阵和非奇异矩阵)

a = np.array([[3,3.5,2],[3.2,3.6,3],[6,7,4]])
np.linalg.matrix_rank(a)
  • 矩阵求逆

AA-¹=A-¹A=E(单位矩阵)
http://jingyan.baidu.com/album/1709ad8095e1924634c4f03a.html

  • 逆矩阵作用

逆矩阵是经常遇到的一个概念。教科书中讲解了逆矩阵的求法,但是没有说清楚为何需要逆矩阵,逆矩阵的意义是什么。逆矩阵可以类比成数字的倒数,比如数字5的倒数是1/5,矩阵A的“倒数”是A的逆矩阵。5(1/5)=1, A(A的逆矩阵) = I,I是单位矩阵。引入逆矩阵的原因之一是用来实现矩阵的除法。比如有矩阵X,A,B,其中XA = B,我们要求X矩阵的值。本能来说,我们只需要将B/A就可以得到X矩阵了。但是对于矩阵来说,不存在直接相除的概念。我们需要借助逆矩阵,间接实现矩阵的除法。具体的做法是等式两边在相同位置同时乘以矩阵A的逆矩阵,如下所示,XA(A的逆矩阵)= B(A的逆矩阵)。由于A(A的逆矩阵) = I,即单位矩阵,任何矩阵乘以单位矩阵的结果都是其本身。所以,我们可以得到X = B(A的逆矩阵)。

  • numpy矩阵求逆
a_ = np.linalg.inv(a)

四.岭回归

  • 原理


    岭回归原理.png
  • 缩减系数来“理解”数据


    图1.png
  • 优点

缩减方法可以去掉不重要的参数,因此能更好地理解数据。此外,与简单的线性回归相比,缩减法能取得更好的预测效果;
岭回归是加了二阶正则项的最小二乘,主要适用于过拟合严重或各变量之间存在多重共线性的时候,岭回归是有bias的,这里的bias是为了让variance更小。

  • 过拟合

过拟合即是过分拟合了训练数据,使得模型的复杂度提高,泛化能力较差(对未知数据的预测能力)
下面左图即为欠拟合,中图为合适的拟合,右图为过拟合。


过拟合.png
  • 总结

1.岭回归可以解决特征数量比样本量多的问题
2.岭回归作为一种缩减算法可以判断哪些特征重要或者不重要,有点类似于降维的效果
3.缩减算法可以看作是对一个模型增加偏差的同时减少方差

  • 应用场景

1.数据点少于变量个数
2.变量间存在共线性(最小二乘回归得到的系数不稳定,方差很大)
3.应用场景就是处理高度相关的数据

实例

1.导入

import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression #普通线性回归
from sklearn.linear_model import Ridge #岭回归

2.假数据

x = [[1,1,1],[1,2,3]]
y = [3,1]

3.普通线性回归

from sklearn.linear_model import LinearRegression

# 第0步
reg1 = LinearRegression()

# 第1步
reg1.fit(X,y)

reg1.predict(np.array([[2,2,2]]))

4.岭回归

from sklearn.linear_model import Ridge

# 第0步
reg2 = Ridge()
# 第1步
reg2.fit(X,y)
reg2.predict([[2,2,2]])
  • 拓展
import numpy as np
import matplotlib.pyplot as plt
from sklearn import linear_model

# X is the 10x10 Hilbert matrix
X = 1. / (np.arange(1, 11) + np.arange(0, 10)[:, np.newaxis])
y = np.ones(10)

###############################################################################
# Compute paths

n_alphas = 200
alphas = np.logspace(-10, -2, n_alphas)
clf = linear_model.Ridge(fit_intercept=False)

coefs = []
for a in alphas:
    clf.set_params(alpha=a)
    clf.fit(X, y)
    coefs.append(clf.coef_)

###############################################################################
# Display results
plt.figure(figsize=(12,9))
ax = plt.gca()


ax.plot(alphas, coefs)
ax.set_xscale('log')
ax.set_xlim(ax.get_xlim()[::-1])  # reverse axis
plt.xlabel('alpha')
plt.ylabel('weights')
plt.title('Ridge coefficients as a function of the regularization')
plt.axis('tight')
plt.show()
拓展图.png

五.Lasso回归

least absolute shrinkage and selection operator,最小绝对值收缩和选择算子
与岭回归类似,它也是通过增加惩罚函数来判断、消除特征间的共线性。


岭回归1.png

当λ足够小时,一些影响较弱的系数会因此被迫缩减到0

  • 优点

跟岭回归类似,不同的算法

实例 : 波士顿房价信息

1.导入

from sklearn.linear_model import Lasso
from sklearn.datasets import load_boston
boston=load_boston()

2.数据处理

X=boston.data[:-20]
Y=boston["target"][:-20]
X_test = boston.data[-20:]
Y_test = boston['target'][-20:]
names=boston["feature_names"]

3.使用lasso

lasso=Lasso(alpha=0.7)
lasso.fit(X,Y)
display(lasso.predict(X_test),Y_test)

六.普通线性回归、岭回归、Lasso回归比较

通过案例来进行比较

1.导入模块

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# 根据实际值与预测值,给模型打分
from sklearn.metrics import r2_score 

2.准备数据

np.random.seed(42) #给numpy随机数指定种子,这样生成随机数,就会固定

n_samples,n_features = 50,200

#生成样本
x = np.random.randn(n_samples,n_features)

#系数,也就是W
coef = 3*np.random.randn(n_features)

#系数归零化索引
inds = np.arange(n_features)

#打乱顺序
np.random.shuffle(inds)

#对系数进行归零化处理
coef[inds[10:]] = 0

#目标值
y = np.dot(x,coef)

#增加噪声
y += 0.01*np.random.normal(n_samples)

3.训练数据/测试数据

# 训练数据
x_train,y_train = x[:n_samples//2],y[:n_samples//2]
#测试数据
x_test,y_test = x[n_samples//2:],y[n_samples//2:]

4.普通线性回归

#使用普通线性回归
from sklearn.linear_model import LinearRegression
lreg = LinearRegression()

#训练数据
lreg.fit(x_train,y_train)

#预测数据
y_pred = lreg.predict(x_test)
r2_score(y_test,y_pred)

5.岭回归

#使用岭回归
from sklearn.linear_model import Ridge
ridge = Ridge()

#训练数据
ridge.fit(x_train,y_train)

#预测数据
y_pred = ridge.predict(x_test)

#获取回归模型的分数
r2_score(y_test,y_pred)

6.Lasso

from sklearn.linear_model import Lasso

lasso = Lasso()

lasso.fit(x_train,y_train)

y_pred_lasso = lasso.predict(x_test)

r2_score(y_test,y_pred_lasso)

7.绘制图标展示数据

# 画出参数
plt.figure(figsize=(12,8))

plt.subplot(221)
plt.plot(reg.coef_,color = 'lightgreen',lw = 2,label = 'lr coefficients')
plt.legend()

plt.subplot(222)
plt.plot(reg2.coef_,color = 'red',lw = 2,label = 'ridge coefficients')
plt.legend()

plt.subplot(223)
plt.plot(reg3.coef_,color = 'gold',lw = 2,label = 'lasso coefficients')
plt.legend()

plt.subplot(224)
plt.plot(coef,color = 'navy',lw = 2,label = 'original coefficients')
plt.legend()
回归比较.png

七.logistics

  • 什么是逻辑斯蒂函数


    逻辑斯蒂图1.png

    逻辑斯蒂图2.png

    根据现有数据对分类边界线建立回归公式,依此进行分类

  • 逻辑斯蒂回归---->分类

利用Logistics回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,以此进行分类。这里的“回归” 一词源于最佳拟合,表示要找到最佳拟合参数集

Logistic Regression和Linear Regression的原理是相似的,可以简单的描述为这样的过程

(1)找一个合适的预测函数,一般表示为h函数,该函数就是我们需要找的分类函数,它用来预测输入数据的判断结果。这个过程是非常关键的,需要对数据有一定的了解或分析,知道或者猜测预测函数的“大概”形式,比如是线性函数还是非线性函数
(2)构造一个Cost函数(损失函数),该函数表示预测的输出(h)与训练数据类别(y)之间的偏差,可以是二者之间的差(h-y)或者是其他的形式。综合考虑所有训练数据的“损失”,将Cost求和或者求平均,记为J(θ)函数,表示所有训练数据预测值与实际类别的偏差
(3)显然,J(θ)函数的值越小表示预测函数越准确(即h函数越准确),所以这一步需要做的是找到J(θ)函数的最小值。找函数的最小值有不同的方法,Logistic Regression实现时有梯度下降法(Gradient Descent)

  • 站在巨人的肩膀上


    图1.png

    图2.png

    图3.png

    图4.png

    举个例子

假如有一个罐子,里面有黑白两种颜色的球,数目多少不知,两种颜色的比例也不知。我 们想知道罐中白球和黑球的比例,但我们不能把罐中的球全部拿出来数。现在我们可以每次任意从已经摇匀的罐中拿一个球出来,记录球的颜色,然后把拿出来的球 再放回罐中。这个过程可以重复,我们可以用记录的球的颜色来估计罐中黑白球的比例。假如在前面的一百次重复记录中,有七十次是白球,请问罐中白球所占的比例最有可能是多少?很多人马上就有答案了:70%。而其后的理论支撑是什么呢?

    我们假设罐中白球的比例是p,那么黑球的比例就是1-p。因为每抽一个球出来,在记录颜色之后,我们把抽出的球放回了罐中并摇匀,所以每次抽出来的球的颜 色服从同一独立分布。这里我们把一次抽出来球的颜色称为一次抽样。题目中在一百次抽样中,七十次是白球的概率是P(Data | M),这里Data是所有的数据,M是所给出的模型,表示每次抽出来的球是白色的概率为p。如果第一抽样的结果记为x1,第二抽样的结果记为x2... 那么Data = (x1,x2,…,x100)。这样,

    P(Data | M)

     = P(x1,x2,…,x100|M)

     = P(x1|M)P(x2|M)…P(x100|M)

     = p^70(1-p)^30.

那么p在取什么值的时候,P(Data |M)的值最大呢?将p^70(1-p)^30对p求导,并其等于零。

    70p^69(1-p)^30-p^70*30(1-p)^29=0。

    解方程可以得到p=0.7。

在边界点p=0,1,P(Data|M)=0。所以当p=0.7时,P(Data|M)的值最大。这和我们常识中按抽样中的比例来计算的结果是一样的。
  • 优缺点

实现简单,易于理解和实现;计算代价不高,速度很快,存储资源低
容易欠拟合,分类精度可能不高

实战
  • 手写数字数据集的分类
    1.导入
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression

2.处理数据

digits = datasets.load_digits()
x_digits = digits.data
y_digits = digits.target

x_train = x_digits[:round(.9*len(x_digits))]
x_test = x_digits[round(.9*len(x_digits)):]

y_train = y_digits[:round(.9*len(y_digits))]
y_test = y_digits[round(.9*len(y_digits)):]

3.训练和预测

knn = KNeighborsClassifier()
logistic = LogisticRegression()

display('KNN score: %f'%knn.fit(x_train,y_train).score(x_test,y_test),
       'Logistic Score: %f'%logistic.fit(x_train,y_train).score(x_test,y_test))
  • 使用make_blobs产生数据集进行分类
    1.导入
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

from sklearn.datasets import make_blobs #生成用于聚类的各向同性高斯斑点
from sklearn.linear_model import LogisticRegression

2.处理数据

# 设置三个中心点,建立一个三分类问题
centers = [[-5,0],[0,1.5],[5,-1]]
X,y = make_blobs(n_samples=1000, centers=centers, random_state=40)

3.训练数据

# 第1步:训练
clf = LogisticRegression()
clf.fit(X,y)

4.图片背景图片点

# 背景(网格)
h = 0.02
x_min,x_max = X[:,0].min()-1,X[:,0].max()+1
y_min,y_max = X[:,1].min()-1,X[:,1].max()+1

# 从坐标向量返回坐标矩阵
# 图片的背景显示坐标
xx,yy = np.meshgrid(np.arange(x_min,x_max,h),
                   np.arange(y_min,y_max,h))

5.预测数据

# 得到网格上每个点的分类情况
Z = clf.predict(np.c_[xx.ravel(),yy.ravel()])
z = Z.reshape(xx.shape)
#预测背景图片的点,从而知道划分区域

6.画图

# 画图
plt.figure()
#绘制轮廓线,填充轮廓
#plt.contourf(xx,yy,z,cmap = plt.cm.Paired)
plt.pcolormesh(xx,yy,z,cmap = plt.cm.Paired)
plt.title("Logistic Regression")
plt.axis('tight')

colors = 'bry'
for i,color in zip(clf.classes_,colors):
    idx = np.where(y==i)
    plt.scatter(X[idx,0],X[idx,1],c=color,cmap = plt.cm.Paired)
分类图.png

八.人脸自动补全

1.导包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.neighbors import KNeighborsRegressor
from sklearn.ensemble import ExtraTreesRegressor
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_olivetti_faces

2.提取数据

#加载人脸数据
faces = fetch_olivetti_faces()
#生成训练数据和预测数据
data = faces.data
target = faces.target
# 上半部分脸是训练数据,下半部分脸是预测数据.
face_up = data[:,:2048] # 训练数据
face_down = data[:,2048:] # 标记
# 拆分数据,留一些做预测数据
X_train,X_test, y_train,y_test = train_test_split(face_up, face_down, test_size=0.1)

3.训练模型

#创建机器学习模型,以字典的形式包含四种模型
estimators = {
    'knn': KNeighborsRegressor(),
    'linear': LinearRegression(),
    'ridge': Ridge(),
    'extratree': ExtraTreesRegressor()
}

4.训练数据并预测数据

y_pred = {}
for key,estimator in estimators.items():
    # 训练
    estimator.fit(X_train,y_train)
    # 预测
    y_ = estimator.predict(X_test)
    y_pred[key] = y_
    

5.绘制人脸预测图像

#绘制预测的人脸
# 展示结果.
# 8行6列
plt.figure(figsize=(8* 3,6* 3.5))
for i in range(8):
    axes = plt.subplot(8,6, i * 6 + 1)
    # 拼出完整的脸
    face_up = X_test[i*5].reshape(32,64)
    face_down = y_test[i*5].reshape(32,64)
    face = np.vstack((face_up,face_down))
    axes.imshow(face, cmap='gray')
    # 去掉轴
    axes.axis('off')
    # 加个标题
    if i == 0:
        axes.set_title('True', fontdict=dict(fontsize=20))
        
    # 第二列显示真实的上半部分脸
    axes = plt.subplot(8,6, i*6 + 2)
    axes.imshow(face_up, cmap='gray')
    axes.axis('off')
    if i == 0:
        axes.set_title('half face', fontdict=dict(fontsize=20))
        
    # 循环的画出后面四列
    for j,key in enumerate(y_pred):
        axes = plt.subplot(8,6, i*6 + 3 + j)
        # 拼出真实上半部分脸和下半部分脸的结合
        face_down_pred = y_pred[key][i*5].reshape(32,64)
        face_pred = np.vstack((face_up, face_down_pred))
        axes.imshow(face_pred, cmap='gray')
        if i == 0 :
            axes.set_title(key, fontdict=dict(fontsize=20))
        axes.axis('off')

效果图


人脸识别.png

推荐阅读更多精彩内容