'''
多变量线性回归:预测房屋价格,其中有2个特征:房子的大小,卧室的数量。
'''
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 数据文件路径
path = 'data/ex1data2.txt'
# 读取数据文件:path(文件路径),header(列名),names(为数据命名)
# header=None时,即指明原始文件数据没有列索引,这样read_csv会自动加上列索引,除非你给定列索引的名字。
data = pd.read_csv(path, header=None, names=['Size', 'Bedrooms', 'Price'])
# print(data.head())
# 特征缩放(特征归一化):data.mean()得到每列数据的平均值,data.std()得到每列数据的标准偏差
# 标准偏差:一种度量数据分布的分散程度之标准,用以衡量数据值偏离算术平均值的程度
data = (data - data.mean()) / data.std()
# 定义代价函数,返回代价值
def computeCost(X, y, theta):
inner = np.power(((X * theta.T) - y), 2) # np.power(x,y):计算x的y次方(inner计算结果一个列向量)
return np.sum(inner) / (2 * len(X)) # np.sum(矩阵):对矩阵内的所有元素求和
# 在训练集中添加一列,以便我们可以使用向量化的解决方案来计算代价和梯度。
# loc(int型,表示第几列;若在第一列插入数据,则 loc=0),column(给插入的列取名),value(列值)
data.insert(0, 'ones', 1)
# 变量初始化
cols = data.shape[1] # cols存放数据集的列数(3列)
X = data.iloc[:, 0:cols - 1] # X存放数据集的前cols-1(2列)的数据
y = data.iloc[:, cols - 1:cols] # y存放数据集的最后一列数据
# 将上述的X与y变量值转换为 matrix 形式
X = np.matrix(X.values)
y = np.matrix(y.values)
theta = np.matrix([0, 0, 0]) # 参数向量,初始值都为 0
print('初始代价:', computeCost(X, y, theta)) # 计算初始代价函数的值
# 批量梯度下降,返回参数值和代价值
def gradientDescent(X, y, theta, alpha, epoch): # epoch为迭代次数
temp = np.matrix(np.zeros(theta.shape)) # temp用于更新参数θ向量
cost = np.zeros(epoch) # cost[epoch]数组存放每次迭代梯度下降后的代价值
m = X.shape[0] # m存放样本总数量
# 批量梯度下降
for i in range(epoch):
# 利用向量化一步求解
temp = theta - (alpha / m) * (X * theta.T - y).T * X # 新参数θ向量
theta = temp # 赋值
cost[i] = computeCost(X, y, theta) # 记录每次的迭代后代价值
return theta, cost
# 初始化变量
alpha = 0.01 # 学习率
epoch = 1000 # 迭代次数
# 运行梯度下降算法,优化参数θ向量
final_theta, cost = gradientDescent(X, y, theta, alpha, epoch)
# 打印最后的代价值
print('最后的代价值:', computeCost(X, y, final_theta))
print('final_theta:', final_theta)
# 画代价函数图
fig, ax = plt.subplots(figsize=(12, 8))
ax.plot(np.arange(epoch), cost, 'r')
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title('Error vs. Training Epoch')
plt.show()
运行结果: