今天就来学一学简单的线性回归模型(Simple Linear Regession Model),也就是通常所说的单变量线性回归模型。按照上节的分类,它属于监督模型中的回归算法。线性回归模型可以说是很多机器学习模型的基础(Basic)。更重要的是求解线性回归模型中的一些方法,比如梯度下降(Gradient Desecent)等更是被大家所熟知,被用于各种模型当中来求解。
梯度下降
线性回归模型可以用来干什么呢?其实用途蛮大的,比如房价预测,股票走势等连续变化量的预测。
废话不多说,本节学习教程分三步:首先Sklearn实现,随后Tensorflow实现,最后Numpy,Pandas两人登场。前两个属于黑盒子,无脑操作;后面一个需要理解算法背后的原理。看大家自己选择喽~~~~数据下载提取码:y6qt
Numpy面前都是弟弟
1、Sklearn的简单线性回归模型(开始花里胡哨一波操作)
#数据:学习时间和分数
Hours Scores
0 2.5 21
1 5.1 47
2 3.2 27
3 8.5 75
4 3.5 30
5 1.5 20
6 9.2 88
7 5.5 60
8 8.3 81
9 2.7 25
10 7.7 85
11 5.9 62
12 4.5 41
13 3.3 42
14 1.1 17
15 8.9 95
16 2.5 30
17 1.9 24
18 6.1 67
19 7.4 69
20 2.7 30
21 4.8 54
22 3.8 35
23 6.9 76
24 7.8 86
#一般来说拿到数据,不是直接上模型,首先画出数据图像分布
import matplotlib.pyplot as plt
import pandas as pd
dataset=pd.read_csv(path)#利用pd读取数据,注意路径
x=dataset.iloc[:,:1].values#注意x要是一个二维数组
y=dataset.iloc[:,1].values#注意y是一维数组
plt.scatter(x,y)
plt.xlabel('Time/Hours')
plt.ylabel('Score')
plt.title('Time and Score')
plt.show()
Time and Score
据我推断还是挺符合线性关系的啊(这不是废话嘛)
推理也很好
确定使用线性回归模型以后,Sklearn手起刀落,全世界都静止了
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=0)
首先把数据拆分为训练集和测试集,还不会的同学可以参考机器学习数据预处理
from sklearn.linear_model import LinearRegression as LR#导入线性回归模型
lr=LR()#将类实例化
lr.fit(x_train,y_train)#实例化对x,y训练集进行训练
y_pre=lr.predict(x_test)#用训练好的模型去预测测试集的x,并返回预测值y_pre
#数据可视化一下
plt.scatter(x,y)
plt.xlabel('Time/Hours')
plt.ylabel('Score')
plt.title('Time and Score')
plt.plot(x,lr_predict(x),color='red')
plt.show()
简单线性回归
Sklearn的强大就在于此,世界上最快的男人,搭建简单的机器学习模型十分得心应手,但是问题在于我们并没有清晰的认识到底程序是怎么工作的,这就是很多教程不友好的地方,也是我觉得网络资源杂的原因。
2、Tensorflow的简单线性回归模型(大家都是TF-boys)
损失函数(Cost Function)的选取:
线性回归模型h(x)=theta0+x*theta1一般选取最小均方差作为损失函数,损失函数表示为J(theta0,theta1)=
损失函数
m表示样本的数量,这个公式说起来其实就是最小二乘法。也可以说是预测值和真实值之间的欧几里得距离之和的均值
最小优化损失函数
我们的目的当然很明显,就是要让损失函数最小,我们的直线才能拟合得很好。在微积分中,要求二元函数(这里就是损失函数)的最小值,通常采取求偏导,并让偏导数等于0即可。
迭代方法
梯度下降,沿着梯度方向进行下降,损失函数能最快达到局部最小值。theta的更新迭代式为
参数更新
即theta沿着自己的梯度方向进行数值更新,直到达到局部最小(a为学习速率)。(进一步了解线性回归模型请点击)跳出迭代的条件为:1、两次迭代之间的差值大于阈值.2、迭代次数达到限制。
TensorFlow库函数的讨论
通常TensorFlow中的优化方法(Optimizer 优化器)被集成在train模块中。Optimizer类用来计算损失函数的梯度,常用的有梯度下降(Gradient descent),Adam,Adagrad等。使用的步骤为
import tensorflow as tf
opt=tf.train.GradientDescentOptimizer()#参数为学习速率,创建优化方法
option_on_opt=opt.minimize(loss,var_list)#对优化方法求最小值,参数loss存放每轮迭代后数值,var_list是变量列表。
Tips:TensorFlow内部有计算梯度的compute_gradients函数。同时Opitimizer优化器还包括AdagradOptimizer,AdadeltaOptimizer,MomentumOptimizer等等
TensorFlow单变量线性回归实战
import twnsorflow as tf
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
rng=np.random
dataset=pd.read_csv(path)#path是数据文件存储路径
x=dataset.iloc[:,:1].values
y=dataset.iloc[:,1].values#注意上面是小写x,y
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.25,random_state=0)#将训练集打散,这个就不多说,数据预处理里面提到过
n_samples=x_train.shape[0]#获取训练集的行数
learning_rate=0.01#定义学习率,上述a
train_epoch=1000#定义迭代次数
display_step=50#定义每隔多少次显示当前学习成果
X=tf.placeholder("float")#定义装纳x_train的浮点数常量容器
Y=tf.placeholder("float")#同理定义y_train的
theta_1=tf.Variable(rng.randn(),name='weight')#定义theta_1的变量容器和名称,并赋予初始值,初始值为标准正态分布中的一个数
theta_0=tf.Variable(rng.randn(),name='bias')#同理定义theta_0
pred=tf.add(tf.multiply(X,theta_1),theta_0)#定义要预测的值的表达式,必须全部用容器表示
cost=tf.reduce_sum(tf.pow(pred-Y,2)/(2*n_samples))#定义损失函数,也必须用容器表示
optimizer=tf.train.GradientDecentOptimizer(learning_rate).minimize(cost)#定义优化函数为梯度下降的优化器,优化器的目的是使得损失函数cost最小,并赋予学习率
init=tf.global_variables_initializer()#定义全局初始化函数,以上使用的容器尚未被初始化传入数值
with tf.Session() as sess:
sess.run(init)#所有变量初始化
for epoch in range(train_epoch):#训练迭代次数
for (x,y) in zip(x_train,y_train):#运行优化器,并将x_train和y_train的值喂给容器
sess.run(optimizer,feed_dict={X:x,Y:y}
if (epoch+1)%diasplay_step==0:#进行可视化,打印出cost,theta_1,theta_0
c=sess.run(cost,feed_dict={X:x_train,Y:y_train})
print("Epoch:","%04d"%(epoch+1),"cost=","{:.9f}".format(c),"theta_1=",sess.run(theta_1),"theta_0=",sess.run(theta_0))
print("Optimizer Finished")
training_cost=sess.run(cost,feed_dict={X:x_train,Y:y_train})
print("Train_cost=",training_cost,"theta_1=",sess.run(theta_1),'theta_0=',sess.run(theta_0),'\n')#run谁得到谁的值
#以下是matplot的可视化
plt.plot(x_train,y_train,'ro',label='Origin data')
plt.plot(x_train,sess.run(theta_1)*x_train+sess.run(theta_0),label='Fitted_line')
plt.legend()
plt.show()
Tensorflow的简单线性回归模型就到这里,是不是相对Sklearn来说方法更清晰了,那下面我们就来介绍自己动手做线性回归模型。
俗话说:轮子虽好,我手更巧。下面的内容就将使用基本的Numpy等函数求解线性回归模型,我们目前采用主流的直接法求解和梯度下降的方法。
线性回归的直接法求解(最小二乘法求解)
对于一个简单的线性回归模型,我们假设它的模型表达式为
线性回归模型
在前面我们提到梯度下降的损失函数(Cost Function),其实在这里有稍微的改动
损失函数(这里没有平均值了呀)
用向量表示的推导过程如下:
损失函数
然后对系数W进行求导,并令其为0,得到W的取值,即为最小二乘法的解。
w的解
import pandas as pd
dataset=pd.read_csv(path)
x=dataset.iloc[:,:1].values
list_x=x.tolist()#这一步的目的是把X处理成向量
for i in list_x:
i.insert(0,1)
x=np.array(list_x)
y=dataset.iloc[:,1].values
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=0)
#以上是导入数据并拆散为训练集和测试集
#有一点需要注意的是对于x的形式,X包括X0和X1,X0是构造的1,X1是数据的本身特征。
w=(np.mat(x_train).T*np.mat(x_train)).I*np.mat(x_train).T*np.mat(y_train).T
#这里的Y之所以转置,是因为Y不处理前是1*n向量,所以对它进行转置
#以上就是系数求解,预测如下
def predict(x,w):
y_pre=x.dot(w)
return y_pre
import matplotlib.pyplot as plt
plt.scatter(c,y)
plt.plot(x,predict(x,w))
plt.show()!
结果
怎么说,还行吧,但是呢,这种方法只适合数据比较小的数据集,遇到比较大的数据集,还是采用下面的梯度下降的方法
线性回归模型的梯度下降方法求解
#梯度下降方法求解简单线性回归模型
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
dataset=pd.read_csv(PATH)#CSV文件路径
x=dataset.iloc[:,:1].values
y=dataset.iloc[:,1].values
x_list=x.tolist()
for i in x_list:
i.append(1)
x=np.array(x_list)#将x==>[x,1]
#以上是导入数据,不再多啰嗦;并对x进行预处理得到向量的X
def cost_function(h=np.array([1,3,5,7,9]),y=np.array([2,4,6,8,10])):
shape=h.shape[0]
cost=((h-y)**2).sum()/(2*shape)
return cost
#计算损失函数,很简单的
def GradientDecent(theta=np.array([np.random.normal(),np.random.normal()]),alpha=0.005,iteration=1500,x=np.array([[1,2],[1,4],[1,6]]),y=np.array([1,3,5])):
m=y.shape[0]
J_history=np.zeros(iteration)
theta=theta-alpha*(1/m)*((x.T).dot((x.dot(theta.T)-y)))#对theta的值进行迭代(Tensorflow处给出迭代公式),嗯注意向量(矩阵)的求导
for j in range(iteration):
theta=theta-alpha*(1/m)*((x.T).dot((x.dot(theta.T)-y)))
J_history[j]=cost_function(x.dot(theta.T),y)#记录每一步的损失函数值,观察收敛状况
return (theta,J_history)
#梯度下降进行迭代
theta,J_history=GradientDecent(alpha=0.0001,iteration=5000,x=x,y=y)
plt.scatter(dataset.iloc[:,:1].values,y)
plt.plot(dataset.iloc[:,:1].values,x.dot(theta.T))
plt.show()#绘出图像
plt.plot(np.arange(0,iteration),J_history)
plt.show()
成果展示
拟合结果
损失函数收敛情况
到这里,线性回归模型的操作拟合基本就介绍完,但是目前还是比较初级,对正则化啊,多元线性回归啊,岭回归啊等都尚未涉及,欲知后事如何,请看下集。
我哭了,生活太难了










网友评论