多变量批量梯度下降python代码
2023-12-13 09:04:25
前面几篇分别完成了单变量的处理,其中数据本身范围比较合理以至于损失值没有太离谱。本篇使用的数据集的目标值y和特征X的量级差距过大,因此引入了目标变量的特征归一化处理。
未处理归一化之前的损失:
初始的损失值: 65591548106.45744
下优化后的损失值: 2043280050.607604
处理归一化之后的损失:
初始的损失值: 0.5
下优化后的损失值: 0.13352749098585492
在图片绘制阶段,进行了逆归一化处理。最终绘制图片如下:
具体代码如下:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import joblib
# 导入数据
path = 'ex1data2.txt'
data = pd.read_csv(path, header=None, names=['Population', 'City Size', 'Profit'])
# 分离特征和目标变量
X = data.iloc[:, 0:2].values # Population和City Size列
y = data.iloc[:, 2].values # Profit列
def normalize(array):
mean = np.mean(array, axis=0)
std = np.std(array, axis=0)
normalized_array = (array - mean) / std
return normalized_array, mean, std
# 使用函数分别归一化特征和目标变量
X_norm, mean_X, std_X = normalize(X)
y_norm, mean_y, std_y = normalize(y)
# 添加截距项
m = len(y) # 样本数量
X_norm = np.append(np.ones((m, 1)), X_norm, axis=1)
# 初始化模型参数
theta = np.zeros(3)
# 批量梯度下降参数
alpha = 0.01 # 学习率
iterations = 3000 # 迭代次数
# 批量梯度下降算法
def gradientDescent(X, y, theta, alpha, num_iters):
m = len(y)
for i in range(num_iters):
predictions = X.dot(theta)
errors = np.subtract(predictions, y)
sum_delta = (alpha / m) * X.transpose().dot(errors)
theta = theta - sum_delta
return theta
"""
下降前的损失显示
"""
# 模型评估
def computeCost(X, y, theta):
predictions = X.dot(theta)
square_err = (predictions - y) ** 2
return np.sum(square_err) / (2 * m)
# 计算初始损失
initial_cost = computeCost(X_norm, y_norm, theta)
print("初始的损失值:", initial_cost)
"""
批量梯度下降
"""
# 进行梯度下降以拟合模型
theta = gradientDescent(X_norm, y_norm, theta, alpha, iterations)
"""
下降后的损失显示
"""
# 计算优化后的损失
final_cost = computeCost(X_norm, y_norm, theta)
print("下优化后的损失值:", final_cost)
"""
使用需要预测的数据X进行预测
"""
# 假设的人口和城市大小数据
population_values = [2000, 4000] # 代表35,000和70,000人口
city_size_values = [2, 3] # 假设的城市大小值,例如使用平均城市大小
# 对每个人口值进行预测
for pop, city_size in zip(population_values, city_size_values):
# 首先将原始特征值归一化
pop_norm = (pop - mean_X[0]) / std_X[0]
city_size_norm = (city_size - mean_X[1]) / std_X[1]
# 然后将人口值和城市大小转换为与训练数据相同的格式(包括截距项)
predict_data = np.array([1, pop_norm, city_size_norm]) # 添加截距项
# 使用模型进行预测
predict_profit_norm = np.dot(predict_data, theta)
# 将预测结果转换回原始尺度
predict_profit = predict_profit_norm * std_y + mean_y
print(f"模型预测结果 - 人口: {pop}, 城市大小: {city_size} : {predict_profit}")
"""
使用模型绘制函数
"""
# 创建3D图形
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d', elev=0, azim=80) # 修改视角
# 使用归一化的特征创建网格
x1_grid, x2_grid = np.meshgrid(np.linspace(X_norm[:, 1].min(), X_norm[:, 1].max(), 100),
np.linspace(X_norm[:, 2].min(), X_norm[:, 2].max(), 100))
# 计算对应网格点的预测值(归一化尺度)
f_grid_norm = theta[0] + (theta[1] * x1_grid) + (theta[2] * x2_grid)
# 逆归一化预测值
f_grid = f_grid_norm * std_y + mean_y
# 逆归一化 x 和 y 轴的特征范围(用于绘图)
x1_grid_original = x1_grid * std_X[0] + mean_X[0]
x2_grid_original = x2_grid * std_X[1] + mean_X[1]
# 绘制训练数据点(使用原始尺度)
ax.scatter(data['Population'], data['City Size'], data['Profit'], color='b')
# 绘制预测平面(使用逆归一化的预测值和原始尺度的特征范围)
ax.plot_surface(x1_grid_original, x2_grid_original, f_grid, color='r', alpha=0.5)
# 设置原始尺度的轴标签
ax.set_xlabel('Population')
ax.set_ylabel('City Size')
ax.set_zlabel('Profit')
ax.set_title('Predicted Profit vs. Population Size and City Size')
plt.show()
同样的,最常用的多变量小批量梯度下降代码也放在这里了,将批量梯度下降的算法换成了小批量,效果基本差不多:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import joblib
# 导入数据
path = 'ex1data2.txt'
data = pd.read_csv(path, header=None, names=['Population', 'City Size', 'Profit'])
# 分离特征和目标变量
X = data.iloc[:, 0:2].values # Population和City Size列
y = data.iloc[:, 2].values # Profit列
def normalize(array):
mean = np.mean(array, axis=0)
std = np.std(array, axis=0)
normalized_array = (array - mean) / std
return normalized_array, mean, std
# 使用函数分别归一化特征和目标变量
X_norm, mean_X, std_X = normalize(X)
y_norm, mean_y, std_y = normalize(y)
# 添加截距项
m = len(y) # 样本数量
X_norm = np.append(np.ones((m, 1)), X_norm, axis=1)
# 初始化模型参数
theta = np.zeros(3)
# 定义批次大小
batch_size = 32 # 例如,32
# 批量梯度下降参数
alpha = 0.01 # 学习率
iterations = 3000 # 迭代次数
# 小批量梯度下降算法
def miniBatchGradientDescent(X, y, theta, alpha, num_iters, batch_size):
m = len(y) # 获取样本数量
for iter in range(num_iters): # 对于每次迭代
cost = 0 # 初始化本次迭代的总成本
indices = np.random.permutation(m) # 随机打乱样本的索引
X_shuffled = X[indices] # 根据打乱的索引重新排列X
y_shuffled = y[indices] # 根据打乱的索引重新排列y
for i in range(0, m, batch_size): # 将数据分成多个批次进行迭代
X_i = X_shuffled[i:i+batch_size] # 获取当前批次的X
y_i = y_shuffled[i:i+batch_size] # 获取当前批次的y
prediction = np.dot(X_i, theta) # 计算当前批次的预测值
error = prediction - y_i # 计算误差
theta = theta - (alpha / batch_size) * np.dot(X_i.T, error) # 更新参数
cost += computeCost(X_i, y_i, theta) # 计算并累加当前批次的成本
return theta # 返回最终参数
"""
下降前的损失显示
"""
# 模型评估
def computeCost(X, y, theta):
predictions = X.dot(theta)
square_err = (predictions - y) ** 2
return np.sum(square_err) / (2 * m)
# 计算初始损失
initial_cost = computeCost(X_norm, y_norm, theta)
print("初始的损失值:", initial_cost)
"""
批量梯度下降
"""
# 进行梯度下降以拟合模型
theta = miniBatchGradientDescent(X_norm, y_norm, theta, alpha, iterations, batch_size)
"""
下降后的损失显示
"""
# 计算优化后的损失
final_cost = computeCost(X_norm, y_norm, theta)
print("下优化后的损失值:", final_cost)
"""
使用需要预测的数据X进行预测
"""
# 假设的人口和城市大小数据
population_values = [2000, 4000] # 代表35,000和70,000人口
city_size_values = [2, 3] # 假设的城市大小值,例如使用平均城市大小
# 对每个人口值进行预测
for pop, city_size in zip(population_values, city_size_values):
# 首先将原始特征值归一化
pop_norm = (pop - mean_X[0]) / std_X[0]
city_size_norm = (city_size - mean_X[1]) / std_X[1]
# 然后将人口值和城市大小转换为与训练数据相同的格式(包括截距项)
predict_data = np.array([1, pop_norm, city_size_norm]) # 添加截距项
# 使用模型进行预测
predict_profit_norm = np.dot(predict_data, theta)
# 将预测结果转换回原始尺度
predict_profit = predict_profit_norm * std_y + mean_y
print(f"模型预测结果 - 人口: {pop}, 城市大小: {city_size} : {predict_profit}")
"""
使用模型绘制函数
"""
# 创建3D图形
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d', elev=0, azim=80) # 修改视角
# 使用归一化的特征创建网格
x1_grid, x2_grid = np.meshgrid(np.linspace(X_norm[:, 1].min(), X_norm[:, 1].max(), 100),
np.linspace(X_norm[:, 2].min(), X_norm[:, 2].max(), 100))
# 计算对应网格点的预测值(归一化尺度)
f_grid_norm = theta[0] + (theta[1] * x1_grid) + (theta[2] * x2_grid)
# 逆归一化预测值
f_grid = f_grid_norm * std_y + mean_y
# 逆归一化 x 和 y 轴的特征范围(用于绘图)
x1_grid_original = x1_grid * std_X[0] + mean_X[0]
x2_grid_original = x2_grid * std_X[1] + mean_X[1]
# 绘制训练数据点(使用原始尺度)
ax.scatter(data['Population'], data['City Size'], data['Profit'], color='b')
# 绘制预测平面(使用逆归一化的预测值和原始尺度的特征范围)
ax.plot_surface(x1_grid_original, x2_grid_original, f_grid, color='r', alpha=0.5)
# 设置原始尺度的轴标签
ax.set_xlabel('Population')
ax.set_ylabel('City Size')
ax.set_zlabel('Profit')
ax.set_title('Predicted Profit vs. Population Size and City Size')
plt.show()
注:本文为学习吴恩达版本机器学习教程的代码整理,使用的数据集为https://github.com/fengdu78/Coursera-ML-AndrewNg-Notes/blob/f2757f85b99a2b800f4c2e3e9ea967d9e17dfbd8/code/ex1-linear%20regression/ex1data2.txt
文章来源:https://blog.csdn.net/eevee_1/article/details/134947847
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!