简介

这是一个最简单的线性回归例子,图解了算法和相关代码。

详解

前提说明

参数估计中均方误差是指参数估计值与参数真值之差平方的期望值,记为MSE。

要想是预测y=wx+b中的线性回归在大量的x和y都知道的情况下预测w,b。那么对于这种无解析解,那么就需要用到机器学习推出w,b的值,那么mse越小,模型训练的就越好,w,b的值也就越准确。

反之w,b越准确,训练出来的模型也就越好,模型越好,处理的数据也就越真实。

开始训练

前提依赖

pip install sklearn

训练数据

[[5.344187740028914], [30.91441332291272]][[4.690797837330457], [17.989132245249227]][[3.06514407164054], [32.67390058378043]][[0.29136844635404446], [-15.046942990405128]][[2.7042454045721764], [-4.198779971237319]][[9.15496044375243], [54.50659423843143]][[4.323588254945952], [76.06219903136115]]

直接上代码

#!/usr/bin/python# -*- coding: UTF-8 -*-import sysimport numpy as npfrom sklearn.linear_model import LinearRegressionfrom sklearn import metricsdef curce_data(x,y,y_pred):x=x.tolist()y=y.tolist()y_pred=y_pred.tolist()results=zip(x,y,y_pred)results=["{},{},{}".format(s[0][0],s[1][0],s[2][0]) for s in results ]return resultsdef read_data(path):with open(path) as f :lines=f.readlines()lines=[eval(line.strip()) for line in lines]X,y=zip(*lines)X=np.array(X)y=np.array(y)return X,y#这里得到的数据情况。#原始数据# [[5.344187740028914], [30.91441332291272]]# [[4.690797837330457], [17.989132245249227]]# [[3.06514407164054], [32.67390058378043]]# 得到的X_train:# [[5.344187740028914],[4.690797837330457],[3.06514407164054]]#得到的y_train#[[30.91441332291272],[17.989132245249227],[32.67390058378043]]X_train,y_train=read_data("train_data")X_test,y_test=read_data("test_data")#一个对象,它代表的线性回归模型,它的成员变量,就已经有了w,b. 刚生成w和b的时候 是随机的model = LinearRegression()#一调用这个函数,就会不停地找合适的w和b 直到误差最小model.fit(X_train, y_train)#打印Wprint (model.coef_)#打印bprint (model.intercept_)#模型已经训练完毕,用模型看下在训练集的表现y_pred_train = model.predict(X_train)#sklearn 求解训练集的mse# y_train 在训练集上 真实的y值# y_pred_train 通过模型预测出来的y值#计算  (y_train-y_pred_train)^2/ntrain_mse=metrics.mean_squared_error(y_train, y_pred_train)print ("训练集MSE:", train_mse)#看下在测试集上的效果y_pred_test = model.predict(X_test)test_mse=metrics.mean_squared_error(y_test, y_pred_test)print ("测试集MSE:",test_mse)train_curve=curce_data(X_train,y_train,y_pred_train)test_curve=curce_data(X_test,y_test,y_pred_test)print ("推广mse差", test_mse-train_mse)'''with open("train_curve.csv","w") as f :f.writelines("\n".join(train_curve))with open("test_curve.csv","w") as f :f.writelines("\n".join(test_curve))'''

下面是得到的结果

可以看到测试的MSE相对训练的MSE会大一点。

原因是:

测试集里面只有少量的包含了训练集的数据。这个时候测试集的mse就会要高一点,如果测试集在训练集里面那么可能就会低。

还有就是求mse为什么用平方:

因为尽量的放大mse,对于得到的收益也越大,预测成功的数据也会越广。

还有就是如果是常数,那么就没有办法做梯度下降算法。

梯度下降

推导

对于上面的y=x*w+b求mse公式的优化。

用导数求mse的最小值。关于mse的导数,也叫做梯度,&mse/&w关键在于调整w的值,然后得到mse的最小值,也就是如果&mse/&w>0,那么这是一个单调递增的,如果想找到mse的最小值,那么w就要变小。如果&mse/&w<0,那么就是单调递减。我们要找到mse的最小值,那么w就要变大。

,,

但是这里有一个问题,如果很平滑这个抛物线,那么怎么改变它的速度呢?

上面就是对于改变的w,增加一个学习因子,简单的理解就是步长的意思(根据经验给值)。

结论

简单的理解就是:

如果想找到mse的最小值,那么就根据mse对于w求导数,让后启动w的值得到最少的mse,那么这个w就是要找到的训练模型的值。

训练集数量问题

下图对应的是全部数量集,和部分数量集的相关想性。

mse越小越好吗?

不是,因为会出现过拟合的情况。就是避免特例,影响大多数。

上图就是在一个合适的时候,停止学习。

怎么判断是否学过了,可以按时间分别的学习,如果mse开始变大了,那么前面的mse相对就会好一点。

多元分析mse

比如房价预测,x1地段,x2时间….,预测y最后的房价。

公式

开始训练

# -*- encoding:utf-8 -*-from sklearn import datasetsfrom sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegressionfrom sklearn.model_selection import cross_val_predictfrom numpy import shapefrom sklearn import metricsimport numpy as npdef extend_feature(x):result=[x[0],x[0]]result.extend(x[1:])return result#return [x[0],x[0]]def read_data(path):with open(path) as f :lines=f.readlines()lines=[eval(line.strip()) for line in lines]X,y=zip(*lines)X=[extend_feature(x) for x in X]X=np.array(X)y=np.array(y)return X,y#train_data里面的数据#[[3.69311, 0.0, 18.1, 0.0, 0.713, 6.376, 88.4, 2.5671, 24.0, 666.0, 20.2, 391.43, 14.65], 17.7]#[[0.06211, 40.0, 1.25, 0.0, 0.429, 6.49, 44.4, 8.7921, 1.0, 335.0, 19.7, 396.9, 5.98], 22.9]#这里就是得到了x的数组,和对应y的数组#x[[3.69311, 0.0, 18.1, 0.0, 0.713, 6.376, 88.4, 2.5671, 24.0, 666.0, 20.2, 391.43, 14.65],[0.06211, 40.0, 1.25, 0.0, 0.429, 6.49, 44.4, 8.7921, 1.0, 335.0, 19.7, 396.9, 5.98]]#y[17.7,22.9]X_train,y_train=read_data("train_data")X_test,y_test=read_data("test_data")  model = LinearRegression()#对于得到的x,y分别的数组进行训练model.fit(X_train, y_train)#得到对应的w,bprint (model.coef_)#打印wprint (model.intercept_)#打印b#根据得到的模型,输入x,得到yy_pred = model.predict(X_train)#根据预测的数值和真实的数值求mse,mse越小的,模型训练的也就越好。w,b也就越准确print ("MSE:", metrics.mean_squared_error(y_train, y_pred))y_pred = model.predict(X_test)print ("MSE:", metrics.mean_squared_error(y_test, y_pred))  

得到的结果

线性回归花式玩法

处理多元数据有随机数的情况

在多元处理模型的时候,如果有些数太乱,也就是错误数据,比如下面的x4是随机的,那么求出来的w4接近于零。也就是对于最后的运算结果影响不会太大,但是会消耗计算机的计算能力。

处理x数据有重复的情况(分析维度冗余)

模型结果有相同的情况

结论

线性回归最好数据在一条直线上。

如果x的比比较大就会形成抛物线,如下图。

训练出来大概的模型是。

得到的结果图

数据一定尽量真实才能通过训练出来的模型,更具x得到y。

也就是说,线性回归在多个维度,只要数据足够的真实都能够得到对应的模型,预测y的值。

还有就是维度不是越多越好,如果维度太多,模型过于拟和,对于后面的预测不准确

总之使用 线性回归的时候,取的维度适中,不能过拟合,数据也要足够的真实。