参考:吴恩达机器学习系列课后习题(视频)
作业及代码:https://pan.baidu.com/s/1L-Tbo3flzKplAof3fFdD1w 密码:oin0
编程环境:Jupyter Notebook
本课程8道编程作业及解析见:Coursera吴恩达机器学习编程作业
Programming Exercise 1:Linear Regression
本章目录
1. 单变量线性回归
题目
餐馆老板想在不同城市开分店,并收集了这些城市的 人口数 和 当地餐馆的利润 作为训练样本保存在 ex1data1.txt:
请利用线性回归,根据城市的人口数据预测其利润。
1.1 导入数据
-
导入库:
import numpy as np # 科学计算库,处理多维数组,进行数据分析 import pandas as pd # 基于 NumPy 的一种解决数据分析任务工具 import matplotlib.pyplot as plt # 提供一个类似 Matlab 的绘图框架
-
导入数据集:
data = pd.read_csv('ex1data1.txt',names=['population','profit']) # 读取文件,指定列名
可以用
data.head()
和data.tail()
查看 数据集 的 前几组数据 和 倒数几组数据: -
数据可视化
扫描二维码关注公众号,回复: 10558104 查看本文章data.plot.scatter('population','profit',label='profit of population') # 绘制散点图 plt.show()
得到利润和人口的分布散点图:
1.2 构造数据集
已知单变量线性回归的假设函数为:
-
获取数据集中的输入向量 ,需要在数据集加入 的一列:
data.insert(0,'$x_0$',1) # 在 data 第 0 列插入列名为 x_0 值为 1 的列
用
data.head()
验证下是否插入:
-
通过切片操作获取输入向量和输出向量:
cols = data.shape[1] # 获取 data 的列数 X = data.iloc[:,0:cols-1] # X 为 0~cols-1列,所有行 y = data.iloc[:,cols-1:cols] # y 为倒数第 1 列,所有行
用
X.head()
和y.head()
验证:
-
此时 和 的数据结构为DataFrame,需要转换为ndarray类型才能用于后续的矩阵操作:
X = X.values y = y.values
可以用
X.shape
和y.shape
查看数组的维度 ,维度分别为(97,2)和(97,1) -
初始化参数向量 :由于 的维度等于 的维度,计算得到 的维度为(2,1),并初始化为0
theta = np.zeros((2,1))
1.3 代价函数
其中第二项表示向量 自身的内积(公式推导见:线性回归模型向量化 1.3)
define costFunction(X, y, theta):
inner = np.power(X @ theta - y, 2) # power(*,2)使向量(Xθ-y)每一项平方,返回仍为向量
reture np.sum(inner) / (2 * len(X)) # 求向量每一项之和,结果相当于(Xθ-y)自身的内积
1.4 梯度下降函数
(公式推导见:线性回归模型向量化 1.4)
-
定义梯度下降函数:
def gradientDescent(X,y,theta,alpha,iters): # iters为梯度下降中的迭代次数 costs = [] # 将每次迭代的代价函数值保存在列表 for i in range(iters): theta = theta - (X.T @ (X@theta - y) ) * alpha / len(X) cost = costFunction(X,y,theta) costs.append(cost) if i % 100 == 0: print(cost) #每迭代 100 次打印一次cost return theta,costs
-
给学习率
alpha
和迭代次数iters
赋上初值:alpha = 0.02 iters = 1000 theta,costs = gradientDescent(X,y,theta,alpha,iters) #返回迭代1000次后
-
绘制曲线图使代价函数可视化:
fig,ax = plt.subplots() #创建绘图实例 ax.plot(np.arange(iters),costs) ax.set(xlabel='iters', ylabel='cost', title='cost vs iters') plt.show()
1.5 拟合直线可视化
-
绘制迭代后拟合的直线 ,并与原始数据在同一坐标轴
# 创建绘图实例 fig,ax = plt.subplots() #绘制拟合直线 x = np.linspace(y.min(),y.max(),100) y_ = theta[0,0] + theta[1,0] * x ax.plot(x,y_,'r',label='predict') #绘制原始数据散点图 ax.scatter(X[:,1],y,label='training data') #显示直线和散点图的标签 ax.legend() #设置横纵轴名 ax.set(xlabel='populaiton', ylabel='profit') plt.show()
- 打印出
theta
即得到迭代后更新的参数值,然后给出新的population即可预测出其对应的profit
2. 多变量线性回归
题目
假设你现在打算卖房子,想知道房子能卖多少钱?
我们拥有房子面积、卧室数量 与 房子价格之间的对应数据: ex1data2.txt
2.1 导入数据
-
导入库:
import numpy as np # 科学计算库,处理多维数组,进行数据分析 import pandas as pd # 基于 NumPy 的一种解决数据分析任务工具 import matplotlib.pyplot as plt # 提供一个类似 Matlab 的绘图框架
-
导入数据集:
data = pd.read_csv('ex1data2.txt',names=['size','bedrooms','price']) # 读取文件,指定列名 data.head()
-
特征归一化
由于房子面积和卧室数量的尺度相差很大,在提取特征向量之前需要先进行特征归一化(具体原因见 特征缩放)
def normalize_feature(data): return (data - data.mean()) / data.std() # data.mean()为均值,data.std()为方差 data = normalize_feature(data) data.head()
可见归一化后的特征大部分都分布在[-1,1]之间。
- 数据可视化
# 获取坐标分布 X1 = data.iloc[:,0:1] X2 = data.iloc[:,1:2] Y= data.iloc[:,-1] fig = plt.figure() ax = fig.gca(projection='3d') # 创建三维坐标 ax.scatter(X1,X2,Y) # 散点图 ax.set(xlabel='size',ylabel='bedrooms',zlabel='price')# 坐标轴 plt.show()
得到房子价格与房子面积、房间数量的散点图:
2.2 构造数据集
# 添加 x_0=1这一列
data.insert(0,'$x_0$',1)
# 通过切片操作获取输入向量和输出向量
cols = data.shape[1]
X = data.iloc[:,0:cols-1]
y = data.iloc[:,cols-1:cols]
# 将dataframe转成数组
X = X.values
y = y.values
可以用 X.shape
和 y.shape
查看数组的维度 ,维度分别为(47, 3)和(47, 1)
2.3 代价函数
# 同上
define costFunction(X, y, theta):
inner = np.power(X @ theta - y, 2)
reture np.sum(inner) / (2 * len(X))
theta = np.zeros((3,1)) #注意theta的维度变化
2.4 梯度下降函数
def gradientDescent(X,y,theta,alpha,iters,isprint=False):
costs = []
for i in range(iters):
theta = theta - (X.T @ (X@theta - y) ) * alpha / len(X)
cost = costFunction(X,y,theta)
costs.append(cost)
if i % 100 == 0:
if isprint:
print(cost)
return theta,costs
- 不同alpha下的梯度下降效果
candidate_alpha = [0.0003,0.003,0.03,0.0001,0.001,0.01] iters = 2000 fig,ax = plt.subplots() for alpha in candidate_alpha: _,costs = gradientDescent(X,y,theta,alpha,iters) ax.plot(np.arange(iters),costs,label = alpha) ax.legend() ax.set(xlabel='iters', ylabel='cost', title='cost vs iters') plt.show()
2.5 拟合平面可视化
由于有两个变量,最终的拟合结果是三维空间中的一个平面。
-
以
alpha=0.003
,iters=2000
为例,就能得到迭代结束后的最终参数theta_final
,并得到拟合平面: -
将拟合平面与原始散点数据放在同一个三维坐标系中:
%matplotlib notebook # 有时候创建的三维图不能动态展示,加这个就可以 fig = plt.figure() ax = fig.gca(projection='3d')#创建三维坐标 #绘制原始数据的散点图 ax.scatter(X1,X2,Y) # 绘制拟合平面 x1, x2 = np.meshgrid(np.linspace(-2,3.5,2), np.linspace(-3,2.5,2))#生成网格采样点,这一步很重要 h_x = theta[0,0] + theta[1,0] * x1 + theta[2,0] * x2 ax.plot_wireframe(x1,x2,h_x,color='g',alpha = 0.4) #绘制线框 alpha表示透明度 ax.plot_surface(x1,x2,h_x,color='g',alpha = 0.5) #绘制平面 ax.set(xlabel='size',ylabel='bedrooms',zlabel='price')# 坐标轴 plt.show()
3. 正规方程
正规方程的推到见 线性回归模型向量化及正规方程
def normalEquation(X,y):
theta = np.linalg.inv(X.T@X)@X.T@y
return theta
theta = normalEquation(X,y)