Pyhton 3.7
目录
- Multivariate linear regression
- 1.0 package
- 1.1 load data
- 1.2 visualization data
- 1.3 data processing
- 1.4 define costfunction
- 1.5 gradientdescend
- 1.6 visualization result
- 1.7 prediction
Multivariate linear regression
题目:现有多组房屋面积及卧室数目与房价的信息,希望通过这些信息,利用多元线性回归,预测出房价与房屋面积与卧室数目的关系。
1.0 package
同样,首先引入必要包,代码如下:
import numpy as np
# 矩阵运算,数据处理
import pandas as pd
# 格式转换,数据加工
import matplotlib.pyplot as plt
# 绘图必备
from mpl_toolkits.mplot3d import Axes3D
# 绘制3D图
1.1 load data
读取数据,代码如下:
def load_data(path):
# 定义函数,名为loda_data,传入一个参数path
data=pd.read_csv(path,header=None,names=['size','bedrooms','price'])
# 读取数据,自定义列索引分别为'size','bedrooms','price'
return data,data.head(),data.describe()
# 返回数据集,及其头文件(为了简单描述数据),和数据的统计信息
data,data_head,data_describe=load_data('ex1data2.txt')
#调用函数
#print(data_head)
#print(data_describe)
输出如下:
1.2 visualization data
这是一个三维数据,所以好像可视化好像并没有很大帮助,不过还是给出相应代码,供读者自行探究:
def view_data():
# 定义函数,名为view_data
fig=plt.figure()
# 创建一个画布
ax=Axes3D(fig)
# 创建对象,指明为3D对象
ax.scatter(data['size'],data['bedrooms'],data['price'],color='r')
# 绘制散点图,其中参数依次为:横坐标(x1),纵坐标(x2),竖坐标(y),颜色
plt.show()
# 可视化
view_data()
# 调用函数
结果如下:
1.3 data processing
相对于单特征线性回归,这里增加了特征缩放(事实上没有特征缩放也可以,特征缩放事实上旨在将不同特征的数值转换到几乎同一量级,从而加快梯度下降的速度),下面给出代码:
def scaling(data):
# 定义函数,名为scaling,传入参数data
data2=(data-np.mean(data))/(np.std(data))
# 说白了就是归一化,减去均值再除以标准差(注意这里仍然是Dataframe形式)
return data2
# 返回归一化后的data2
data2=scaling(data)
# 调用函数,归一化data
#print(data2.head())
# 查看归一化后结果
输出如下:
嗯对的,现在两类特征的量级已经相同了。
下面是其它一些预处理操作:
data2.insert(0,'one',1)
# 向data2(Dataframe)中第0列(也就是我们认知的第一列)加入一列1,并且将索引设置为one
cols=data2.shape[1]
# 返回data2中列数
x=np.array((data2.iloc[:,0:cols-1]).values)
# 从data2中抽取前cols行,并且将其转换为二维数组,作为x
y=np.array((data.iloc[:,2:]).values)
# 同上,不过注意这里是从原数据中抽取,否则将y也归一化了
#print(x.shape) (47,3)
# 返回x的形状
#print(y.shape) (47,1)
# 返回y的形状
#这里说一下,一定要时不时返回一下矩阵形状,或查看数据类型,不然可能debug一天
theta=np.array([[0,0,0]])
# 初始化 theta
# print(theta.shape) (1,3)
1.4 define costfunction
开始定义代价函数,放图:
其中:
很简单,下面给出代码:
def costfunction(x,y,theta):
# 定义函数,名为costfuncton,传入三个参数:x,y,theta
h=x@theta.T
# 计算h_{theta}x
temp=np.power((h-y),2)
# 计算(h-y)^{2},注意这里返回的仍然是数组
J=np.sum(temp)/(2*len(x))
# 计算代价函数
return J
# 返回代价函数值
cost=costfunction(x,y,theta)
# 调用函数,并将返回值赋值于cost,即cost=J
print(cost)
#查看初始损失 65591548106.45744(当然如果y用的是归一化后的就另当别论了)
1.5 gradientdescend
定义好了损失函数,下面进入算法核心:梯度下降,首先放图:
下面给出代码:
def gradientdescend(x,y,theta,alpha,num_iter):
# 定义函数,名为gradientdescend,传入参数:x,y,theta,alpha,num_iter
theta_t=np.array(np.zeros(theta.shape))
# 创建一个和theta同形状的数组,作为中间变量存储theta值
cost=np.zeros(num_iter)
# 记录每次迭代后的损失函数值
m=len(x)
for i in range(num_iter):
# 开始迭代
theta_t=theta-(alpha/m)*(x@theta.T-y).T@x
# 开始迭代
theta=theta_t
# 将每次迭代后的theta_t赋值给theta,以便下次迭代使用
cost[i]=costfunction(x,y,theta)
# 记录每次迭代后的损失函数值
return theta,cost
# 返回theta(返回的theta就是最后一次迭代的theta,也就是希望的theta)
alpha=0.01
# 赋值学习率
iterations=1000
# 指明迭代次数
fin_theta,cost=gradientdescend(x,y,theta,alpha,iterations)
# 调用梯度下降函数,并返回相应值。最终的theta大概为:[[340397.96353532 108742.65627238 -5873.22993383]]
fin_cost=costfunction(x,y,fin_theta)
# 返回最终的代价函数值,大致为2043498948.1433072
print('fin_theta:',fin_theta,fin_theta.shape)
print('fin_cost:',fin_cost)
1.6 visualization result
可视化代价函数下降过程:
fig,ax=plt.subplots(figsize=(6,6))
ax.plot(np.arange(iterations),cost,'r')
ax.set_xlabel('iterations')
ax.set_ylabel('costfunction')
ax.set_title('iterations VS costfunction')
plt.show()
结果如下:
1.7 prediction
训练完成一个模型后,就该将其投入使用,代码如下:
a=float(input('please tell me the size of the house:'))
b=float(input('please tell me the bedroom of the house:'))
a=(a-np.mean(data['size']))/np.std(data['size'])
b=(b-np.mean(data['bedrooms']))/np.std(data['bedrooms'])
price=fin_theta[0,0]+fin_theta[0,1]*a+fin_theta[0,2]*b
print('the prediction of the price is:',price)
预测差别可以接受,可能部分读者认为预测结果并不理想,事实上这是因为原数据的分布本就不是较好的线性。
至此,已经完成了对于多特征的线性回归训练。还是那句话,一定要多写。
未经允许,请勿转载。
欢迎交流。