将Pandas DataFrame传入梯度下降函数无输出,NumPy数组可正常运行
梯度下降函数适配Pandas DataFrame列的问题修复
问题描述
我编写了用于拟合y=mx+b最优直线的梯度下降函数,使用NumPy数组作为输入时函数可正常运行并输出结果;但从CSV文件读取Pandas DataFrame的Area和Price列传入该函数后,无任何输出且无报错信息。相关代码如下:
import numpy as np import pandas as pd import os # 切换到脚本所在目录 os.chdir(os.path.dirname(os.path.abspath(__file__))) # 迭代拟合y=mx+b最优直线 def gradient_descent(x,y): m_iter = b_iter = 1 # 初始值 iteration = 10000 n = len(x) learning_rate = 0.05 last_mse = 10000 # 逐步迭代逼近全局最小值 for i in range(iteration): y_predicted = m_iter*x + b_iter # 计算均方误差(损失函数) mse = 1/n*sum((y-y_predicted)**2) if (last_mse - mse)/mse < 0.001: break # 计算MSE对m和b的偏导数 dm = -(2/n)*sum(x*(y-y_predicted)) db = -(2/n)*sum((y-y_predicted)) # 更新m和b的迭代值 m_iter = m_iter - learning_rate*dm b_iter = b_iter - learning_rate*db print('m is {}, b is {}, cost is {}, iteration {}'.format(m_iter,b_iter,mse,i)) last_mse = mse # 测试用NumPy数组(注释状态) #x = np.array([1,2,3,4,5]) #y = np.array([5,7,8,10,13]) #gradient_descent(x,y) # 从CSV读取数据传入函数 df = pd.read_csv('Linear_Data.csv') x = df['Area'] y = df['Price'] gradient_descent(x,y)
问题原因
- 终止条件误触发:初始设置
last_mse=10000,如果CSV中的Area、Price数值远大于测试用的小NumPy数组,第一次计算的MSE会远大于10000,导致(last_mse - mse)/mse为负数,直接满足<0.001的条件,循环在第一次迭代就break,因此没有任何输出。 - Pandas Series与NumPy数组的运算细节差异:虽然Pandas Series支持标量运算,但原生
sum()函数在处理Series时的行为和NumPy数组一致,但结合不合理的终止条件会放大问题。
解决方案
方案一:将Pandas Series转为NumPy数组
直接把DataFrame的列转为NumPy数组,保持原有函数逻辑不变:
df = pd.read_csv('Linear_Data.csv') x = df['Area'].values # 转为NumPy数组 y = df['Price'].values gradient_descent(x,y)
方案二:优化终止条件与运算逻辑
修改终止条件为判断MSE的绝对下降幅度,同时使用NumPy的求和函数避免潜在差异:
def gradient_descent(x,y): m_iter = b_iter = 1 # 初始值 iteration = 10000 n = len(x) learning_rate = 0.05 last_mse = float('inf') # 初始设为无穷大 # 逐步迭代逼近全局最小值 for i in range(iteration): y_predicted = m_iter*x + b_iter # 用np.sum替代原生sum,适配Pandas和NumPy mse = 1/n * np.sum((y-y_predicted)**2) # 判断MSE绝对下降幅度,避免初始迭代误触发 if abs(last_mse - mse) < 1e-6: break # 计算偏导数时同样用np.sum dm = -(2/n)*np.sum(x*(y-y_predicted)) db = -(2/n)*np.sum(y-y_predicted) # 更新m和b的迭代值 m_iter = m_iter - learning_rate*dm b_iter = b_iter - learning_rate*db print('m is {}, b is {}, cost is {}, iteration {}'.format(m_iter,b_iter,mse,i)) last_mse = mse
内容的提问来源于stack exchange,提问作者wew044
相关产品推荐
相关产品推荐

