实验目的
使用Python实现线性回归
实验原理
使用最小二乘法进行线性回归,采用均方误差来表示误差,使用梯度下降法进行最小化误差。
实验内容(表格区域可拉长)
(1)已知样本输入和标签如x.txt和y.txt所示,试使用Python求出i.) y=2x+2;ii.) y=x+3;iii.)y = 3x-1这三条直线哪个更加接近于样本给出的值。
(2)对于上述数据,采用线性回归拟合出该线性方程。
(要求:采用直接读取文件的方式,不要复制粘贴。)
import numpy as np import matplotlib.pyplot as plt x = list() y = list() with open("x.txt", "r") as f: for line in f.readlines(): line = float(line.strip()) x.append(line) # print(x) with open("y.txt", "r") as f: for line in f.readlines(): line = float(line.strip()) y.append(line) loss_sum1 = 0 for i in range(0, 10): a = (2 * x[i] + 2 - y[i]) ** 2 loss_sum1 += a average1 = loss_sum1 / len(x) print("损失值为:%.15f"%average1) loss_sum2 = 0 for i in range(0, 10): b = (x[i] + 3 - y[i]) ** 2 loss_sum2 += b average2 = loss_sum2 / len(x) print("损失值为:%.15f"%average2) loss_sum3 = 0 for i in range(0, 10): b = (3 * x[i] - 1 - y[i]) ** 2 loss_sum3 += b average3 = loss_sum3 / len(x) print("损失值为:%.15f"%average3) if (loss_sum1 < loss_sum2) and (loss_sum1 < loss_sum3): print("y=2x+2更加接近样本给出的值") if (loss_sum2 < loss_sum1) and (loss_sum2 < loss_sum3): print("y=x+1更加接近样本给出的值") else: print("y=3x-1更加接近样本给出的值") # def updatekb(data, k, b, learning_rate): # x=data[0] # y=data[1] # n = len(x) # dk, db = 0, 0 # for i in range(n): # dk += 2 / 10 * (k*x[i] + b - y[i]) * x[i] # db += 2 / 10 * (k * x[i] + b - y[i]) # new_k = k - learning_rate * dk # new_b = b - learning_rate * db # return new_k, new_b # # # def learningcregression(data, k, b, r, h): # dk, db = k, b # n = len(x) # for i in range(n): # dk, db = updatekb(data, dk, db, r) # return dk, db # # # #入口函数 # def getdata(): # x, y = getdata() # return x, y # # # if __name__ == "__main__": # k, b = learningcregression(getdata, 2, 1, 0.001, 10000) # 取步长为0.001 k = [3, 0] b = [-1, 0] ones = 0 while True: dk, db = 0, 0 for i in range(0, 10): dk += 2 / 10 * (k[0] * x[i] + b[0] - y[i]) * x[i] db += 2 / 10 * (k[0] * x[i] + b[0] - y[i]) k[1] = k[0] - 0.001 * dk b[1] = b[0] - 0.001 * db if ones == 100000: break else: k[0] = k[1] b[0] = b[1] ones += 1 print("拟合回归方程的斜率k为:%.7f"%k[1]) print("拟合回归方程的斜率k为:%.7f"%b[1]) print(ones) print("拟合回归方程为:%.7f * x + %.7f" % (k[1], b[1])) x = np.array(x) y = np.array(y) Y = k[1] * x + b[1] plt.scatter(x, y) plt.plot(x, Y, '*-g') plt.show()
思考题(表格区域可拉长)
(1)试引入sklearn包,直接计算该线性方程。(注:选做)
(2)试将上述坐标点和线性方程的图像使用Python画入平面直角坐标系中。
(3)试思考当有2个及以上特征时,如何使用线性回归方法来实现拟合。(注:文字描述即可)
3)当特征值为两个的时候,则是一个二维平面(横纵坐标分别表示一个特征值)。当出现两个以上的特征值时,特征值越多,坐标的维数越多,那么模型建立起来就比较繁琐,而且多特征有时还会存在多重共线性问题,即相互之间具有关联关系,导致解空间不稳定,模型泛化能力弱,过多特征也会妨碍模型学习规律。因此,当特征值比较多时我们通常可以采用降维的方式减少维数,使模型简单准确,简单来说就是指可以用更少维度的特征替代更高维度的特征,同时保留有用的信息,把高维空间上的多个特征组合成少数几个无关的主成分,同时包含原数据中大部分的变异信息,简单的来说就是在二维坐标(x,y)内均匀分布在一条回归线上下,在三维坐标内(x,y,z)还是按照近似二维平面分布,第三个维度(z)对回归拟合的影响非常小,故可以删除这个特征向量(z),用二维(x,y)来反映原始数据,除此之外还有其他的方法进行降维,例如缺失值比率 、低方差滤波 、高相关滤波 、随机森林/组合树等
注:变异信息就用方差来衡量,第一主成分是高维空间上的一个向量,所有的点沿着这条线波动最大,或者说所有的点到直线的距离的平方和最小。如下图所示,所有的点沿着绿色直线的波动最大,它就代表着第一主成分向量。