正在学习线性回归问题,选取的是房价和面积的线性关系。训练数据9组。
h(x)= a*x+b
通过【正规方程法】求得 a=5.8, b=-111
通过【梯度下降法】分别设置a和b的学习率
lr_a =0.000016
lr_b =0.01
迭代2000次也能求得近似 a=5.8, b=-111
但是进行归一化特征缩放后,a=4.8,而b的值每次运行都不一样,代价函数依然能收敛,这是为什么?刚学到线性回归,求通俗解答。
# 导入numpy
import numpy as np
# 导入pandas库
import pandas as pd
# 导入绘图库
from matplotlib import pyplot as plt
# 读取excel文件
df = pd.read_excel('house_price.xlsx')
# 将df某列转化为numpy格式
area = df['Size'].to_numpy()
price = df['Price'].to_numpy()
# 定义归一化方法
def normalize(array):
min_value = np.min(array)
max_value = np.max(array)
return (array - min_value) / (max_value - min_value)
# 对原数据进行归一化
x = normalize(area)
# 为了形式统一,我们虽然定义了y,但注意不要对y进行处理
y = price
print(x)
# 使用平方/均方误差作为代价函数
def cost_function(a,b):
cost = np.sum((a * area + b - price) ** 2)
return cost
def cost_avg_function(a,b):
cost_avg = np.sum((a * area+b - price) ** 2)/len(area)
return cost_avg
# 计算梯度
def grad_a_func(a,b):
grad_a = np.sum((a * area + b - price) * area)
return grad_a
def grad_b_func(a,b):
grad_b = np.sum(a * area + b - price)
return grad_b
# 定义超参数
# 学习率
lr = 0.000016
# 迭代次数
epoch = 1000
# 创建一个数组,记录每一次迭代时的代价,用于最后绘图
cost_log = np.empty(epoch)
# 为待训练参数生成随机初始值
a1 = np.random.randint(10)
b1 = np.random.randint(10)
# 开始迭代
for e in range(epoch):
cost = cost_function(a1, b1)
# 分别计算两个方向上的梯度
gradient_a = grad_a_func(a1, b1)
gradient_b = grad_b_func(a1, b1)
# 同时更新a1和b1
a1 = a1 - lr * gradient_a
b1 = b1 - lr * gradient_b
# 记录本次迭代的代价
cost_log[e] = cost
print(f'当前迭代第{e}次:cost={cost},a={a1},b={b1}')
# 绘制图形
plt.title('Cost Function Curve')
plt.xlabel('Epoch')
plt.ylabel('Cost')
plt.plot(np.arange(epoch), cost_log)
plt.show()
该回答引用ChatGPT
# 导入numpy
import numpy as np
# 导入pandas库
import pandas as pd
# 导入绘图库
from matplotlib import pyplot as plt
# 读取excel文件
df = pd.read_excel('house_price.xlsx')
# 将df某列转化为numpy格式
area = df['Size'].to_numpy()
price = df['Price'].to_numpy()
# 定义归一化方法
def normalize(array):
min_value = np.min(array)
max_value = np.max(array)
return (array - min_value) / (max_value - min_value)
# 对原数据进行归一化
x = normalize(area)
# 为了形式统一,我们虽然定义了y,但注意不要对y进行处理
y = price
# 使用平方/均方误差作为代价函数
def cost_function(a,b):
cost = np.sum((a * area + b - price) ** 2)
return cost
def cost_avg_function(a,b):
cost_avg = np.sum((a * area+b - price) ** 2)/len(area)
return cost_avg
# 计算梯度
def grad_a_func(a,b):
grad_a = np.sum((a * area + b - price) * area)
return grad_a
def grad_b_func(a,b):
grad_b = np.sum(a * area + b - price)
return grad_b
# 定义超参数
# 学习率
lr_a = 0.01
lr_b = 0.001
# 迭代次数
epoch = 2000
# 创建一个数组,记录每一次迭代时的代价,用于最后绘图
cost_log = np.empty(epoch)
# 为待训练参数生成随机初始值
a1 = np.random.randint(10)
b1 = np.random.randint(10)
# 开始迭代
for e in range(epoch):
cost = cost_function(a1, b1)
# 分别计算两个方向上的梯度
gradient_a = grad_a_func(a1, b1)
gradient_b = grad_b_func(a1, b1)
# 同时更新a1和b1
a1 = a1 - lr_a * gradient_a
b1 = b1 - lr_b * gradient_b
# 记录本次迭代的代价
cost_log[e] = cost
print(f'当前迭代第{e}次:cost={cost},a={a1},b={b1}')
# 绘制图形
plt.title('Cost Function Curve')
plt.xlabel('Epoch')
plt.ylabel('Cost')
plt.plot(np.arange(epoch), cost_log)
plt.show()
参考视频: 4 - 5 - Features and Polynomial Regression (8 min).mkv
如房价预测问题,
注:如果我们采用多项式回归模型,在运行梯度下降算法前,特征缩放非常有必要。
我的理解是:你对于x特征做归一化,然而x和y你没有对应缩放。这就好比原式(两组数据(50,100)、(100,200))为:
100 = a*30 + b 和 200 = a*100 + b,
归一化之后变为:
100 = a * 0.3 + b, 200 = a*1.0 + b,求得的b是不一样的,而a是差不多的。因此也需要对y做归一化,即:
0.5 = a * 0.3 + b, 1.0 = a*1.0 + b,也就是说不仅对x做归一化,还要对y做归一化,因为要保持x和y之间的关系不变。
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
在对原数据进行归一化特征缩放后,需要重新求得相应的参数,因为特征归一化会改变原始数据的取值范围,进而影响拟合的结果。通常,归一化的方法是将每个特征的值除以该特征下所有值的方差(或者取归一化后的值减去均值再除以标准差)。
在代码中,定义了normalize()
方法来实现归一化,但该方法中采用的方法是将数据进行最大最小值归一化。可以使用更加通用且稳健的标准差标准化方法,其代码如下:
def normalize(array):
return (array - np.mean(array)) / np.std(array)
该方法将每个特征值减去该特征下所有值的均值,再除以该特征下所有值的标准差。这样,每个特征的均值都变成了0,标准差为1。
在归一化后,计算代价函数的时候需要用到缩放后的数据x
,而非area
。即:
def cost_function(a,b):
cost = np.sum((a * x + b - price) ** 2)
return cost
计算梯度时,同样需要使用缩放后的数据x
进行计算,如下:
def grad_a_func(a,b):
grad_a = np.sum((a * x + b - price) * x)
return grad_a
def grad_b_func(a,b):
grad_b = np.sum(a * x + b - price)
return grad_b
完整代码如下:
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
df = pd.read_excel('house_price.xlsx')
area = df['Size'].to_numpy()
price = df['Price'].to_numpy()
def normalize(array):
return (array - np.mean(array)) / np.std(array)
x = normalize(area)
y = price
def cost_function(a,b):
cost = np.sum((a * x + b - price) ** 2)
return cost
def grad_a_func(a,b):
grad_a = np.sum((a * x + b - price) * x)
return grad_a
def grad_b_func(a,b):
grad_b = np.sum(a * x + b - price)
return grad_b
lr_a = 0.000016
lr_b = 0.01
epoch = 2000
cost_log = np.empty(epoch)
a1 = np.random.randint(10)
b1 = np.random.randint(10)
for e in range(epoch):
cost = cost_function(a1, b1)
gradient_a = grad_a_func(a1, b1)
gradient_b = grad_b_func(a1, b1)
a1 = a1 - lr_a * gradient_a
b1 = b1 - lr_b * gradient_b
cost_log[e] = cost
print(f'当前迭代第{e}次:cost={cost},a={a1},b={b1}')
plt.title('Cost Function Curve')
plt.xlabel('Epoch')
plt.ylabel('Cost')
plt.plot(np.arange(epoch), cost_log)
plt.show()
如果我的回答解决了您的问题,请采纳!