编程练习1:线性回归
1.用一个变量进行线性回归
在这部分的练习中,你将用一个变量来实现线性回归来预测食品卡车的利润。 假设你是一家餐馆特许经营的首席执行官,并正在考虑在不同的城市开设新的出路。 这个连锁店在各个城市已经有卡车,而且你有来自城市的利润和人口数据。您想使用这些数据来帮助您选择要扩展到下一个城市。文件ex1data1.txt包含我们的线性回归概率数据集,第一列是一个城市的人口,第二列是该城市食品卡车的利润,负利润表示亏损。
1.1绘制数据
在开始任何任务之前,通过可视化来理解数据通常是有用的。 对于这个数据集,可以使用散点图来显示数据,因为它只有两个属性来绘制(人口和利润)。
path = r'C:\Users\Administrator\Desktop\ML\machine-learning-ex1\ex1\ex1data1.txt' # 数据地址
data = pd.read_csv(path, header=None, names=['Population', 'Profits']) # 导入数据
data.plot(kind='scatter', x='Population', y='Profits', color='r')
plt.show()
画出散点图图像:
1.2梯度下降
在这一部分中,您将使用梯度下降法将线性回归参数θ拟合到我们的数据集中。该部分分为两部分进行,第一部分是定义代价函数,第二部分是进行梯度下降。
# 定义代价函数,使用向量化
def CostFunction(X, y, theta):
Predictions = X*theta
Cost = np.power((Predictions - y), 2)
J = 1/(2*len(X))*sum(Cost)
return J
data.insert(0, 'Ones', 1) # 添加一列,相当于x0 = 1
X = data.iloc[:, :2] # X取所有行,去掉最后一列作为输出y
y = data.iloc[:, 2] # y取所有行,最后一列
# 代价函数是numpy矩阵,将X和y转换为矩阵
X = np.mat(X)
y = np.mat(y)
y = y.T
# 初始化theta
theta = np.mat([[0], [0]])
# 暂时不进行梯度下降,求在theta=[0,0]时,代价函数的值
J = CostFunction(X, y.T, theta)
print("代价函数在模型参数为[0, 0]时为: ", J)
运行结果:
代价函数在模型参数为[0, 0]时为: [[32.07273388]]
# 定义批量梯度下降
def GradientDescent(X, y, theta, alpha, epoch):
Newtheta = np.mat(np.zeros(theta.shape)) # 初始化theta为0
parameters = int(theta.shape[0]) # 计算参数个数,这里就是2个
cost = np.zeros(epoch) # 初始化cost = 0,记录每迭代一次之后的代价函数的值
for i in range(epoch): # 第一个for循环负责迭代次数
error = (X * theta) - y # 计算预测值和实际值之差
for j in range(parameters): # 第二个for循环对每个参数进行更新
term = np.multiply(error, X[:, j]) # 偏导部分
Newtheta[j, 0] = theta[j, 0] - ((alpha / len(X)) * np.sum(term)) # theta更新一次
theta = Newtheta # 将最终的theta值赋予theta
cost[i] = CostFunction(X, y, theta)
return theta, cost
alpha = 0.01 # 初始化学习率和迭代次数
epoch = 1000
theta, cost = GradientDescent(X, y, theta, alpha, epoch) # 调用函数,返回最终的参数和每次迭代后代价函数的值
print(CostFunction(X, y, theta)) # 查看最终的代价函数的值
运行结果:
[[4.5159555]]
1.3调试,拟合直线
# 根据梯度下降得到的参数画出拟合模型
x = np.linspace(data.Population.min(), data.Population.max(), 100) # 方便画图,形成坐标x的点
f = theta[0, 0] + theta[1, 0] * x # 定义拟合直线f
fig, ax = plt.subplots(figsize=(12, 8)) # 设置画布和大小
ax.plot(x, f, 'r', label='Prediction') # 画出拟合直线
ax.scatter(data.Population, data.Profits, label='Traning Data') # 画出散点图
ax.set_xlabel('Population') # 设置坐标和标题
ax.set_ylabel('Profits')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()
运行结果:
1.4代价函数变化曲线
# 画出代价函数的变化曲线
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()
运行结果:
全部完整代码:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 绘制数据
path = r'C:\Users\Administrator\Desktop\ML\machine-learning-ex1\ex1\ex1data1.txt'
data = pd.read_csv(path, header=None, names=['Population', 'Profits'])
data.plot(kind='scatter', x='Population', y='Profits', color='r')
plt.show()
# 定义代价函数,使用向量化
def CostFunction(X, y, theta):
Predictions = X*theta
Cost = np.power((Predictions - y), 2)
J = 1/(2*len(X))*sum(Cost)
return J
data.insert(0, 'Ones', 1)
X = data.iloc[:, :2]
y = data.iloc[:, 2]
X = np.mat(X)
y = np.mat(y)
y = y.T
theta = np.mat([[0], [0]])
J = CostFunction(X, y, theta)
print("代价函数在模型参数为[0, 0]时为: ", J)
# 定义批量梯度下降
def GradientDescent(X, y, theta, alpha, epoch):
Newtheta = np.mat(np.zeros(theta.shape))
parameters = int(theta.shape[0])
cost = np.zeros(epoch)
for i in range(epoch):
error = (X * theta) - y
for j in range(parameters):
term = np.multiply(error, X[:, j])
Newtheta[j, 0] = theta[j, 0] - ((alpha / len(X)) * np.sum(term))
theta = Newtheta
cost[i] = CostFunction(X, y, theta)
return theta, cost
alpha = 0.01
epoch = 1000
theta, cost = GradientDescent(X, y, theta, alpha, epoch)
print(CostFunction(X, y, theta))
# 根据梯度下降得到的参数画出拟合模型
x = np.linspace(data.Population.min(), data.Population.max(), 100)
f = theta[0, 0] + theta[1, 0] * x
fig, ax = plt.subplots(figsize=(12, 8))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(data.Population, data.Profits, label='Traning Data')
ax.set_xlabel('Population')
ax.set_ylabel('Profits')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()
# 画出代价函数的变化曲线
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()
2.具有多个变量的线性回归
在这一部分中,您将实施具有多个变量的线性回归来预测房屋的价格。假设你正在卖你的房子,你想知道一个好的市场价格是多少。 要做到这一点的一个方法是首先收集最近出售的房屋的信息,并制定房价模型。ex1data2.txt文件的第一列是房子的大小(以平方英尺为单位),第二列是卧室的数量,第三列是房子的价格,即有两个特征变量。
这一部分步骤和单变量线性回归相同,给出代码。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 代价函数
def CostFunction(X, y, theta):
Predictions = X*theta
Cost = np.power((Predictions - y), 2)
J = 1/(2*len(X))*sum(Cost)
return J
# 梯度下降
def GradientDescent(X, y, theta, alpha, epoch):
Newtheta = np.mat(np.zeros(theta.shape))
parameters = int(theta.shape[0])
cost = np.zeros(epoch)
for i in range(epoch):
error = (X * theta) - y
for j in range(parameters):
term = np.multiply(error, X[:, j])
Newtheta[j, 0] = theta[j, 0] - ((alpha / len(X)) * np.sum(term))
theta = Newtheta
cost[i] = CostFunction(X, y, theta)
return theta, cost
# 绘制数据
path = r'C:\Users\Administrator\Desktop\ML\machine-learning-ex1\ex1\ex1data2.txt'
data = pd.read_csv(path, header=None, names=['Size', 'Bedrooms', 'Price'])
# 归一化处理
data = (data - data.mean())/data.std()
# 插入x0 = 1
data.insert(0, 'Ones', 1)
# 为X和y赋值,现在数据集有4列,3列作为特征,最后一列作为输出
cols = data.shape[1]
X = data.iloc[:, :3]
y = data.iloc[:, 3]
# 将X和y转换为矩阵
X = np.mat(X)
y = np.mat(y)
y = y.T
# 初始化theta
theta = np.mat([[0], [0], [0]])
# 定义学习率和迭代次数
alpha = 0.01
epoch = 1000
theta, cost = GradientDescent(X, y, theta, alpha, epoch)
# 画出代价函数变化曲线
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()
运行结果:
3.正则化
直接使用正则化公式求解模型参数
import numpy as np
import pandas as pd
path = r'C:\Users\Administrator\Desktop\ML\machine-learning-ex1\ex1\ex1data1.txt'
data = pd.read_csv(path, header=None)
data.insert(0, 'ones', 1)
cols = data.shape[1]
X = data.iloc[:, :2]
y = data.iloc[:, 2]
X = np.mat(X)
y = np.mat(y)
y = y.T
theta = (X.T * X).I * X.T * y
print(theta)
运行结果:
[[-3.89578088]
[ 1.19303364]]
与梯度下降算法结果相同,但形式上更为简单。