前言
上一篇我们对数据进行了读取并进行了可视化,今天我们来继续实现算法。
完整代码会在最后给出,如果你直接复制下面零散的代码可能会运行不了。
这篇的代码已经默认import了pandas,numpy等模块。
数据标准化
首先我们先取要用的三列数据作为训练数据集:
trainData = cReader[['mpg','displacement','acceleration']]
trainData.insert(0,'ones',1)
cols = trainData.shape[1]
X = trainData.iloc[:,0:cols-1]
Y = trainData.iloc[:,cols-1:cols]
X = np.mat(X.values)
Y = np.mat(Y.values)
for i in range(1,3):
X[:,i] = (X[:,i] - min(X[:,i])) / (max(X[:,i]) - min(X[:,I]))
Y[:,0] = (Y[:,0] - min(Y[:,0])) / (max(Y[:,0]) - min(Y[:,0]))
打印一下trainData前五行数据:
trainData数据
代码说明
在训练数据第一列加一列全为1的列矩阵trainData.insert(0,'ones',1),目的是为了进行线性回归的时候简化计算,因为我们的目标方程是h(x)= θ0+ θ1𝓧1+ θ2𝓧2的一个常数项可以看成是θ0和1的乘积,其他项为θi和𝓧i的乘积
下图βi即为我们的θi
解释
cols得到trainData的列数,shape[0],shape[1]分别是trainData的行数和列数,下面把它的前三行'ones','mpg','displacement'分配给自变量矩阵𝓧最后一列分配给因变量矩阵Y
得到数据之后将它们标准化,关于做线性回归是否需要标准化数据,这里有一个比较好的解释
一般来说,我们再做线性回归时并不需要中心化和标准化数据。大多数情况下数据中的特征会以不同的测量单位展现,无论有没有中心化或者标准化都不会影响线性回归的结果。
因为估计出来的参数值β会恰当地将每个解释变量的单位x转化为响应变量的单位y.
但是标准化数据能将我们的结果更具有可解释性,比如β1=0.6
和β2=0.3, 我们可以理解为第一个特征的重要性是第二个特征的两倍。
这里采用以下公式进行标准化,对应上面代码的最后三行:
离差标准化公式
开始回归
首先用最小二乘法计算回归系数,并给出梯度下降的代价函数的代码表示
最小二乘法公式:
最小二乘法
代码:
theta_n = (X.T*X).I*X.T*Y
print(theta_n)
打印结果: [[ 0.58007057] [-0.0378746 ] [-0.35473364]],从左到右分别是θ0,θ1,θ2
定义代价函数:
公式:
代价函数公式
代码:
我是直接自己定义了一个新模块linearRegrassion.py,在里面写了线性回归相关的函数,这也是上篇文章中开头的import linearReg