线性回归可以通过梯度下降和正规方程的方式进行实现求解,这两种算法各有利弊,下面个给出两种算法的python实现,其中数据集使用的是波士顿房价预估数据集。
1. 梯度下降法进行求解
首先对数据集进行处理, 使用梯度下降算法进行求解时, 将数据集 分为测试集和训练集, 并划分出属性和标签。
import numpy as np
import pandas as pd
import random
import matplotlib.pyplot as plt
# 导入数据集
data = pd.read_csv('./Boston-Housing-Price.csv')
m, n = np.shape(data) # 其中m表示data中样本的数量,n表示属性和标签的总数
data_origin = data.values
data = data_origin/np.mean(data_origin,axis=0)
def split_train_and_test(data,m,n):
# 首先将数组顺序打乱
random.shuffle(data)
# 取出数组的30%作为测试集数据
data_test = data[:m//3,:]
data_train = data[m//3:,:]
# 将测试集和训练集中的属性和标签分出来
data_test_attr = data_test[:,:n-1]
data_test_label = data_test[:,n-1]
data_train_attr = data_train[:,:n-1]
data_train_label = data_train[:,n-1]
return data_test_attr,data_test_label,data_train_attr,data_train_label
data_test_attr,data_test_label,data_train_attr,data_train_label = split_train_and_test(data,m,n)
# 建立线性回归模型,使用矢量进行表示,使用了梯度下降的方式
def train(train_Attr,train_Label,num,alpha):
m,n = np.shape(train_Attr)
weight=np.ones(n) #生成的是一行n列的数组
bias = np.zeros(1)
for i in range(num):
h = np.dot(train_Attr,weight) + bias # 建立了线性回归模型
erro = h-train_Label.T
delt = np.dot(erro.T,train_Attr)
weight = weight-alpha*delt/m
bias = bias - alpha*erro.sum()/m
return weight,bias
weight,bias = train(data_train_attr,data_train_label,200,0.01)
# 进行测试样本的预测
def erro(weight,bias,test_attr,test_label):
predition = np.dot(test_attr,weight) + bias
erro = np.square(predition-test_label).sum()
return erro
list1 = [10,20,30,40,50,60,70,80,90,100,110,120,130,140,150,4000]
erro_list = []
for iteration in list1:
weight, bias = train(data_train_attr, data_train_label, iteration, 0.01)
erro_iter = erro(weight, bias, data_test_attr, data_test_label)
erro_list.append(erro_iter)
# 画出erro随迭代次数的变化曲线
plt.plot(list1,erro_list)
plt.show()
print("最小误差为:",erro_list[-1]) # 大约接近4
2. 正规方程进行求解
import numpy as np
import pandas as pd
import random
# 导入数据集
data = pd.read_csv('./Boston-Housing-Price.csv')
m, n = np.shape(data) # 其中m表示data中样本的数量,n表示属性和标签的总数
data_origin = data.values
insert = np.ones(m)
data_deal = np.insert(data_origin, 0, values=insert, axis=1)
data = data_deal/np.mean(data_deal,axis=0)
def split_train_and_test(data,m,n):
# 首先将数组顺序打乱
random.shuffle(data)
# 取出数组的30%作为测试集数据
data_test = data[:m//3,:]
data_train = data[m//3:,:]
# 将测试集和训练集中的属性和标签分出来
data_test_attr = data_test[:,:n]
data_test_label = data_test[:,n]
data_train_attr = data_train[:,:n]
data_train_label = data_train[:,n]
return data_test_attr,data_test_label,data_train_attr,data_train_label
data_test_attr,data_test_label,data_train_attr,data_train_label = split_train_and_test(data,m,n)
# 根据公式直接计算y_hat
x_xT = np.dot(data_train_attr,data_train_attr.T)
inv_x_xT = np.linalg.pinv(x_xT) # 求的是广义逆矩阵
y_hat = np.dot(np.dot(inv_x_xT,data_train_label),x_xT)
# 直接计算误差值
erro = np.square(y_hat-data_train_label).sum()
print("封闭解结果为:",erro) # 最终的误差值为5.3左右
最终结果分析为:梯度下降算法的应用方面比较广泛,如果再使用一些其他的技巧可能会使算法跳出局部的最优解找到全局的最优解。而正规方程可以一次性的将权值求出,但是限制较大,当xTx不可逆时,此方法便不可以使用。