一. 首先要引进的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
matplotlib.rcParams['font.sans-serif']=['SimHei']#用黑体显示中文,这样做的目的是matplotlib做出的图的轴标签和标题可以用中文表示
二.导入文件
df=pd.read_csv('C:/Users/Administrator/AppData/Local/Temp/Temp2_machine-learning-ex1.zip/machine-learning-ex1/ex1/ex1data1.txt',header=None) #导入文件,此时列名为0和1
df.rename(columns={0:'城市A人口数量',1:'城市A小吃店利润'},inplace=True) #改变列名
df.head()#显示前五行
输出结果
先对该数据做描述性统计(汇总统计),对数据有一个初步的了解:
df.describe()
结果为
三.使用散点图将数据可视化
plt.scatter(df['城市A人口数量'],df['城市A小吃店利润'])
# 设置图表标题并给坐标轴加上标签
plt.title('根据城市人口数量预测该城市小吃店的利润')
plt.xlabel('城市人口数量')
plt.ylabel('城市小吃店利润')
plt.show()
输出结果为:
现在使用梯度下降算法实现线性回归,并使得代价函数最小化
四.定义代价函数
代价函数的公式:
用代码定义:
def computeCost(x,y,theta):
inner = np.sum(np.power((x*theta-y),2))
return inner/(2*len(x)) #theta是指参数
*1. np.power(a,2)是指对数组a逐元素求幂次方
2. np.sum(a)是指对数组a的元素进行求和
因为theta是2*1维的向量,x是len(x) * 1维的向量,为了能进行运算,在x 中第0列前添加一列,其值全为1,这样x变成len(x) *2维的矩阵。此时x * theta就是假设函数。
代码如下:
df.insert(0,'ones',1)#意思是在df的第0列前添加一列,该列的名称为'one',其值全部为1
df.head()
五.定义输入变量和输出变量以及参数
x=df.loc[:,['ones','城市A人口数量']]
y=df.loc[:,'城市A小吃店利润']
X=np.matrix(x.values)
y=np.matrix(y.values)
theta=np.matrix([0,0])
为什么要用np.matrix()呢
因为对于matrix,点乘直接是X*Y,而对于array,点乘是np.dot(X,Y)
我们在前面定义代价函数时,写的是x * theta,而不是np.dot(x,theta)
x.values返回的是array
六.检查输入变量和输出变量以及参数向量的维数
X.shape
y.shape
theta.shape
所以需要调整
y=y.T #去转置
theta=theta.T
七.定义梯度下降算法
首先计算一下最初的代价函数
computeCost(X,y,theta) # 32.072733877455676
定义梯度算法:
def gradientDescent(x,y,theta,alpha,iters):#alpha是学习速率,iters是迭代次数
temp = np.matrix(np.zeros(theta.shape))#初始化
cost = np.zeros(iters) # 初始化
for i in range(iters):
temp = theta - ((alpha/len(x))*(x*theta-y).T *x).T #使用向量的形式
theta = temp # 同时更新
cost[i]=computeCost(x,y,theta)
return theta,cost
1.np.zeros()生成值全为0的array
八.初始化学习速率和迭代次数
alpha=0.01
iters=1000 # 这里取了1000
九.调用梯度下降算法
finally_theta,cost=gradientDescent(X,Y,theta,alpha,iters)
从图片可以看出,随着迭代次数的增加,代价函数值一直在减小
用拟合得到的参数计算训练模型的代价函数
computeCost(X,y,finally_theta) #4.515955503078912
十.绘制线性模型,使其可视化
x=np.linspace(df['城市A人口数量'].min(),df['城市A人口数量'].max(),100)#在城市A人口数量的这一列中选取最小值和最大值,在这两个值之间等间隔的生成100个数字
f=finally_theta[0,0]+finally_theta[1,0]*x
fig,ax=plt.subplots(figsize=(8,4)) #subplots()的用法
ax.plot(x,f,'r',label='预测')
ax.scatter(df['城市A人口数量'],df['城市A小吃店利润'],label='训练集')
ax.legend(loc=2) #在图上标明,用于说明每一条曲线的文字显示
ax.set_xlabel('城市A人口数量')
ax.set_ylabel('城市A小吃店利润')
ax.set_title('根据城市A人口数量预测城市A小吃店利润')
plt.show()
结果为:
补充:
1. np.linspace()在指定间隔内返回均匀间隔的数字
2. 要注意这两种索引的区别:
3.plt.subplots()生成子图
十一.绘制代价函数的曲线
x=np.arange(1000)
fig,ax=plt.subplots(figsize=(8,4))
ax.plot(x,cost,'r')
ax.set_xlabel('迭代次数')
ax.set_ylabel('代价函数值')
ax.set_title('梯度下降')
结果为:
平方误差代价函数是关于参数的二次函数,符合!