线性回归的公式
线性回归的数学推导主要涉及到以下几个知识点。
1. 利用矩阵的知识对线性公式进行整合
2. 误差项的分析
3. 似然函数的理解
4. 矩阵求偏导
5. 线性回归的最终求解
我们先来看下这个图
姓名 | 工资(元) | 房屋面积(平方米) | 可贷款金额(元) |
---|---|---|---|
张三 | 6000 | 58 | 30000 |
李四 | 9000 | 77 | 55010 |
王五 | 11000 | 89 | 73542 |
陆永剑 | 15000 | 54 | 63201 |
这个是近期比较火的现金贷产品的贷款额度。这个表格表示的是可贷款的金额 与 工资 和 房屋面积之间的关系,其中 工资 和 房屋面积 为 特征,可贷款金额为目标函数值。
那么根据线性函数可得到以下公式。
上面的这个式子是当一个模型只有两个特征(x1,x2)的时候的线性回归式子。
正常情况下,现金贷中可贷款的额度和用户的很多特征相关联,并不只是简单的这两个特征。所以我们需要把这个式子进行通用化。
假如有n个特征的话,那么式子就会变成下面的样子
上面的式子是一个多项求和的式子,用机器学习的思想,怎么把这个式子聚合一下呢?
因为机器学习中基本上都是用矩阵的方式来表示参数的,也就是说我们需要把这个多项求和的式子用矩阵的方式表达出来,这样才方便后续的计算。
我们把权重参数和特征参数,都看成是1行n列的矩阵(或者是行向量)。那么就可以根据矩阵乘法的相关知识,把上述多项求和的式子,转换成矩阵的乘法的表达式。
由此我们就把多项求和化简称了
这个就是第一步,利用矩阵的知识对线性公式进行整合。
接着我们来看第二步,误差项的分析
式子里面其实并不是只有W*X吧? 还有一个参数b。也就是我们说的偏移量,或者叫做误差项。
我们先来看下面的这个图
图中的横坐标X1 和 X2 分别代表着 两个特征(工资、房屋平米) 。纵坐标Y代表目标(可贷款的额度)。其中红点代表的就是实际的目标值(每个人可贷款的额度).而平面上和红点竖向相交的点代表着我们根据线性回归模型得到的点。也就是说实际得到的钱和预估的钱之间是有一定误差的,这个就是误差项。
因为误差项是真实值和误差值之间的一个差距。那么肯定我们希望误差项越小越好。
我们根据实际情况,假设认为这个误差项是满足以下几个条件的。
1.独立:张三和李四一起使用这款产品,可贷款额互不影响
2.同分布:张三和李四是使用的是同一款产品
3.高斯分布:绝大多数的情况下,在一个的空间内浮动不大
下面是高斯分布的图,忘记的同学们可以回忆下。
第三步. 似然函数的理解
由前面两步,我们已经把线性回归模型,推导成下面的这个式子了。
第二步,已经知道误差项是符合高斯分布的,所以误差项的概率值就是下面的式子。
再把误差值带入到这个式子里面,就得到了下面的式子。
误差项肯定是越小越好了,那么接下来要讨论的就是什么样的参数和特征的组合能够让误差项最小呢? 这里就引入了似然函数的作用。似然函数的作用就是要根据样本来求什么样的参数和特征的组成能够最接近真实值。越接近真实值则误差越小。
似然函数就是求能让真实值和预测值相等的那个参数的。
上面的式子是多个参数的乘积的形式,很难进行计算,所以我们又采用了对数的一个小技巧,把多个数相乘,转化成多个数相加的形式。
根据上面的这种换算关系,我们就把似然函数的式子换算成下面的这个。
(因为似然函数是越大越好,似然函数的值和对数似然函数的值是成正比的,对值求对数,并不会影响到最后求极限的值。所以才敢进行对数处理。)
对上面的式子进行整合,得到
通过上面一系列推导,就把式子转化为最小二乘法的相关知识了。
这就是在线性回归中使用似然函数的相关知识。
---【如果想了解更多的数学基础知识,及机器学习的相关课程,请点击下面链接】
---【从零开始学习机器学习,包含全套的机器学习课程】
接着看下一步:矩阵求偏导
怎么计算最小二乘法的公式的最小值。这里面就要涉及到导数的相关知识了,
求之前,我们根据矩阵的知识,把上面的式子再转换一下。
把这个式子求一下偏导。
上面的公式里面还涉及到矩阵转置的性质。想了解矩阵转置的性质,请点击此链接【机器学习数学基础】。
将打开的式子,根据矩阵求导的三个重要公式
我们就可以把偏导的值求出来,
最终得到结果:
X和Y都是已知的,那么得到了最终的参数值。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time : 2018/8/12 9:16
# @Author : limingyu
# @Site :
# @File : Test_LinearRegression.py
# @Software: PyCharm
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets,linear_model #提供数据集
#数据集详情: https://blog.csdn.net/eastmount/article/details/52929765
# 这是一个糖尿病的数据集,主要包括442行数据,10个属性值,分别是:
# Age(年龄)、性别(Sex)、Body mass index(体质指数)、Average Blood Pressure(平均血压)、
# S1~S6一年后疾病级数指标。Target为一年后患疾病的定量指标。
#定义线性回归
class LinearRegression():
def __init__(self):
self.w = None
#对数据进行训练,求出最好的参数(斯塔),这里用w表示参数
def fit(self, X, y):
print(X.shape)
X = np.insert(X,0,1,axis=1) #将X0等于1插入矩阵X
X_ = np.linalg.inv(X.T.dot(X))
self.w = X_.dot(X.T).dot(y) #求参数w
#对数据预测
def predict(self,X):
X = np.insert(X,0,1,axis=1)
y_pred = X.dot(self.w) #y'=X0W0+X1W1+X2W2
return y_pred
#定义均方误差
def mean_squared_error(y_true,y_pred):
mse = np.mean(np.power(y_true - y_pred,2))
return mse
if __name__ == '__main__':
#diabetes:[daɪəˈbi:ti:z|糖尿病
diabetes = datasets.load_diabetes() #载入数据
print(diabetes) #数据+类标
#{'data':array([[0.03807591,0.05068012,0.06169621, ..., -0.00259226,0.01990842,-0.01764613],
#'target':array([151., 75., 141., 206., 135., 97.,138., 6等}
print(diabetes.data) #数据
#[[ 0.03807591 0.05068012 0.06169621 ... -0.00259226 0.01990842 -0.01764613]
print(diabetes.target) #类标(标签)
#[151.75.141.206.135.97.138 63.110. 310.101.69.179.185.等]]
print("数据的总行数:",len(diabetes.data)) #数据的总行数: 442
print("类标的总行数:",len(diabetes.target)) #类标的总行数: 442
print("特征数:",len(diabetes.data[0])) #每行数据集维数 特征数: 10
print("数据类型: ", diabetes.data.shape) # 类型 数据类型: (442, 10)
print(type(diabetes.data), type(diabetes.target)) # 数据集类型 <class 'numpy.ndarray'> < class 'numpy.ndarray' >
#仅仅使用一个特征
# 第一个参数:所有行
# 第二个参数:增加一个列维度
# 即仅使用第二列,默认包含所有列
X = diabetes.data[:,np.newaxis,2]
print(X.shape) #(442, 1)
print(X) #[[ 0.06169621]
#[-0.05147406]等]
#数据划分训练集和测试集
x_train = X[:-20] #位置0到位置-20前的数
x_test = X[-20:] #位置-20到位置-1的数即后20个数
print(x_train) #[151. 75. 141. 206. 等]
print(x_test) #[233. 91. 111. 152. 120. 67. 310. 94. 183. 66. 173. 72. 49. 64.
#48. 178. 104. 132. 220. 57.]
#目标(target)划分为训练集和测试集
y_train = diabetes.target[:-20]
y_test = diabetes.target[-20:]
clf = LinearRegression()
clf.fit(x_train,y_train) #训练数据
y_pred = clf.predict(x_test) #预测数据
#得到均方误差
print("Mean Squared Error:",mean_squared_error(y_test,y_pred))
#Mean Squared Error: 2548.072398725972
#可视化展示
plt.scatter(x_test[:,0],y_test,color='black')
plt.plot(x_test[:,0],y_pred,color='blue',linewidth=3)
plt.show()
diabetes数据集github链接:https://github.com/susanli2016/Machine-Learning-with-Python/blob/master/diabetes.csv
机器学习之线性回归入门级:http://blog.51cto.com/12133258/2051527