梯度下降法实战案例(波士顿房价)

本次实战思路是先找到波士顿房价数据中与房价有较强相关性的一列数据,通过梯度下降法找合适的参数,拟合出这列数据与房价的线性关系。

直接上代码

from sklearn.datasets import load_boston
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import numpy as np
import random
%matplotlib inline
dataset = load_boston()#导入数据集
dataframe = pd.DataFrame(dataset['data'])#将数据转成DataFrame格式
dataframe.columns = dataset['feature_names']#添加列索引
dataframe#打印数据
dataframe['price'] = dataset['target']#增加“price”列
dataframe.head()
sns.heatmap(dataframe.corr(), annot=True, fmt='.1f')
#根据相关系数画出热力图,其中越接近1说明这两列数据正相关性越强

基于以上分析,卧室数量和房价正相关较强,我们可以根据卧室数量估计房子价格。

X_rm = dataframe['RM'].values
Y = dataframe['price'].values
rm_to_price = {r: y for r, y in zip(X_rm, Y)}
rm_to_price

可以把卧室数量作为字典的键,房价作为值。用键查找值,假如字典中没有要查询的卧室数量,就会报错。

第一种方法:用K-NN算法思想估计出卧室数量与房价的对应关系

#topn:邻居数量
def knn(history_price, query_x, topn=3):
    #找出与query_x距离最近的topn个卧室数量
    most_similar_items = sorted(history_price.items(), key=lambda e:(e[0] - query_x)**2)[:topn]
    #找出对应的房子价格
    most_similar_prices = [price for rm, price in most_similar_items]
    #求出价格的平均值作为输出结果
    average_prices = np.mean(most_similar_prices)
    
    return average_prices

进行测试

#7个个卧室的房价大约是29.23334
knn(rm_to_price, 7)
#画出卧室数量与房价的散点图 
plt.scatter(X_rm, Y)

散点图给我们提供了另外一种思路,将X_rm和Y拟合成一条直线,找到合适的k和b,我们只需把卧室数量作为变量输入,即可输出得到房价。
第二种方法:拟合线性函数

  • 损失函数
    L o s s ( k , b ) = 1 n ∑ i ∈ N ( y i ^ − y i ) 2 Loss(k, b) = \frac{1}{n} \sum_{i \in N} (\hat{y_i} - y_i) ^ 2 Loss(k,b)=n1iN(yi^yi)2
    L o s s ( k , b ) = 1 n ∑ i ∈ N ( ( k ∗ r m i + b ) − y i ) 2 Loss(k, b) = \frac{1}{n} \sum_{i \in N} ((k * rm_i + b) - y_i) ^ 2 Loss(k,b)=n1iN((krmi+b)yi)2

  • 对k求偏导
    ∂ l o s s ( k , b ) ∂ k = 2 n ∑ i ∈ N ( k ∗ r m i + b − y i ) ∗ r m i \frac{\partial{loss(k, b)}}{\partial{k}} = \frac{2}{n}\sum_{i \in N}(k * rm_i + b - y_i) * rm_i kloss(k,b)=n2iN(krmi+byi)rmi

  • 对b求偏导
    ∂ l o s s ( k , b ) ∂ b = 2 n ∑ i ∈ N ( k ∗ r m i + b − y i ) \frac{\partial{loss(k, b)}}{\partial{b}} = \frac{2}{n}\sum_{i \in N}(k * rm_i + b - y_i) bloss(k,b)=n2iN(krmi+byi)

#损失函数,在这里用的是MSE
def loss(y, yhat):
    return np.mean(np.array(y) - np.array(yhat) ** 2)

#代入k和b,返回预测结果
def model(x, k , b):
    return x * k + b

#对k求偏导
def partial_k(x, y, k, b):
    return 2 * np.mean((y - (k * x + b)) * (-x))#为什么是负值

#对b求偏导
def partial_b(x, y, k, b):
    return 2 * np.mean((y - (k * x + b)) * (-1))

在这里插入图片描述

梯度下降过程:
在微积分中,对多元函数的参数求偏导数,求得参数的偏导数以向量形式表达就是梯度。如图所示,θ₀到θ₁的距离为θ₀在函数L(θ)上的梯度,记做∂L / ∂θ

在数学上,梯度越大,则函数的变化越大。对于函数L(θ)在点θ₀处,梯度向量∂L / ∂θ的方向就是函数L(θ)增加最快的方向。也就是说,沿着梯度向量的方向易于找到函数的最大值。反之亦然,沿着梯度向量相反的方向,梯度减少最快,易于找到函数的最小值。

假设函数L(θ)为损失函数,为了找到损失函数的最小值,需要沿着与梯度向量相反的方向 -∂L / ∂θ更新变量θ,这样可以使梯度减少最快,直到损失收敛至最小值。其基本公式:
θ ← θ − η ∂ L ∂ θ θ ← θ - η\dfrac{∂L}{∂θ} θθηθL

其中,η∈R为学习率,用于控制梯度下降的幅度(快慢)。看上图,梯度下降算法每次计算参数θₓ在当前位置的梯度,然后让参数θₓ顺着梯度的反方向前进一段距离,不断重复该过程。直到梯度接近于零的时候,算法认为找到了损失函数L(θ)的最小值并停止计算。 此时可以认为参数θ*恰好到达让损失函数位于最小值的状态。

VAR_MAX, VAR_MIN = 100, -100#k、b随机取值范围
k, b = random.random(), random.random()
    
min_loss = float('inf')
best_k, best_b = None, None

total_times = 5000#迭代次数
alpha = 1e-2#学习率

k_b_history = []

for t in range(total_times):
    #梯度下降法找k、b的值
    k = k + (-1) * partial_k(X_rm, Y, k, b) * alpha
    b = b + (-1) * partial_b(X_rm, Y, k, b) * alpha
    loss_ = loss(Y, model(X_rm, k, b))
    if loss_ < min_loss:
        min_loss = loss_
        best_k, best_b = k, b
        k_b_history.append((best_k, best_b))
        #print('在{}时刻 我找到了更好的k:{}和b:{}, 这个时候的loss是{}'.format(t, k, b, loss_))

把结果print一下,可以看到几乎在每一个时刻的损失函数值都比上一时刻的更优,说明使用梯度下降法是有效的。

#打印最终的损失函数值
min_loss
#查看拟合效果
plt.scatter(X_rm, Y)
plt.plot(X_rm, best_k * X_rm + best_b, 'yo')

比较两种方法用时

%%time
model(6, best_k, best_b)
%%time
knn(rm_to_price, 6)
事实证明第二种方法比第一种快将近一百万倍!!!

有人会提出来说训练模型的耗时不算嘛?但是相对于knn每次用时那么久,训练出模型一劳永逸就太香了。

本次实战到这里就结束了,假如有喜欢可视化的同学可以透视一下训练过程。

#透视拟合过程
#选取某几个范围内的时刻
test_0 = 0
test_1 = 10
test_2 = 100
test_3 = 5000
test_4 = -1

plt.scatter(X_rm, Y)
plt.scatter(X_rm, k_b_history[test_0][0] * X_rm + k_b_history[test_0][1], color='red')
plt.scatter(X_rm, k_b_history[test_1][0] * X_rm + k_b_history[test_1][1])
plt.scatter(X_rm, k_b_history[test_2][0] * X_rm + k_b_history[test_2][1])
plt.scatter(X_rm, k_b_history[test_3][0] * X_rm + k_b_history[test_3][1])
plt.scatter(X_rm, k_b_history[test_4][0] * X_rm + k_b_history[test_4][1])

完!

  • 4
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 波士顿房价预测是一个经典的回归问题,可以使用梯度下降来解决。以下是一些步骤: 1. 收集和整理数据集,包括波士顿房屋的各种特征(如房间数量、犯罪率、是否靠近河流等)以及其价格。 2. 对数据集进行预处理,例如标准化、归一化等操作,以便更好地训练模型。 3. 构建模型,可以选择使用线性回归模型或其他更高级的模型,例如多项式回归、岭回归等。 4. 定义损失函数,通常使用均方误差(MSE)作为损失函数。 5. 使用梯度下降来优化模型,不断迭代更新参数,使得损失函数最小化。 6. 使用测试数据集来评估模型的性能,可以计算出模型的均方根误差(RMSE)或平均绝对误差(MAE)等指标。 7. 如果模型表现良好,则可以将其用于实际应用中,例如预测新的房屋价格。 需要注意的是,梯度下降需要选择合适的学习率和迭代次数,以避免过拟合或欠拟合的情况。同时,还需要进行特征选择和模型调参等操作,以优化模型的性能。 ### 回答2: 梯度下降是一种常用的机器学习算,用于预测波士顿房价。该算的目标是通过最小化预测值和真实房价之间的平均平方误差来训练模型。 首先,我们需要收集波士顿房价数据,包括不同房屋的特征,如房间数量、犯罪率、学生/教师比例等。然后,将数据分为训练集和测试集。 接下来,我们初始化模型的参数,如截距和特征权重。通过迭代的方式,我们计算每个参数的梯度和损失函数的值,并更新参数值以最小化损失函数。 在每次迭代中,我们选择一个训练样本,并计算预测值与实际房价的差异。然后,使用差异值和该样本的特征值计算每个参数的梯度。在梯度下降中,我们将参数值沿着梯度的方向更新,以减小损失函数。 重复执行上述步骤,直到达到指定的停止条件,例如达到最大迭代次数或损失函数的改进不再显著。在训练完成后,我们可以对模型进行评估,使用测试集计算预测结果与真实房价之间的均方根误差等指标。 梯度下降的优点是它可以处理大量的特征和样本,并且计算速度较快。然而,它可能陷入局部最小值,并且需要适当的学习率来避免震荡或收敛问题。 综上所述,梯度下降是一种有效的预测波士顿房价的算。通过最小化损失函数来优化参数值,我们可以得到用于预测房价的模型。这种方可以应用于各种机器学习问题,并且在波士顿房价预测中取得了较好的效果。 ### 回答3: 梯度下降是一种常用的优化算,用于求解目标函数的最小值。在波士顿房价预测问题中,我们可以将房价作为目标函数,通过梯度下降来找到最佳的模型参数。 首先,我们需要找到一个合适的模型来描述波士顿房价与各个特征之间的关系。常用的模型是线性回归模型,即房价与各个特征之间的线性组合。 然后,我们需要定义一个损失函数,来衡量模型预测值与实际房价之间的差距。通常采用均方误差作为损失函数,即预测值与实际值之间的平方差的均值。 接下来,我们使用梯度下降来更新模型参数。首先随机初始化模型参数,然后通过不断更新参数来最小化损失函数。具体而言,我们计算损失函数对于模型参数的偏导数,然后使用学习率乘以偏导数来更新参数。学习率控制每次更新的步长,可以通过实验来进行调整。 重复以上步骤直到损失函数收敛或达到预设的停止条件。最终得到的模型参数就可以用于预测波士顿房价。 需要注意的是,梯度下降可能陷入局部最优解,因此可以通过设置不同的初始参数和学习率,或者尝试其他优化算(如随机梯度下降、牛顿等)来进一步优化模型性能。 总之,梯度下降是一种常用的优化算,适用于波士顿房价预测问题。通过不断更新模型参数,最小化损失函数,我们可以得到一个较好的预测模型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值