文章目录
- 目标
- 工具
- 概念
- 问题陈述
- 数据集
- 多变量梯度下降
- 学习率
- a=9.9e-7
- a=9e-7
- a=1e-7
- 特征缩放
- 实现
- 恭喜
- 致谢
目标
在本实验中,你将:
- 利用在上一个实验中开发的多变量例程
- 对具有多个特征的数据集运行梯度下降
- 探讨学习率alpha对梯度下降的影响
- 通过使用z-score归一化的特征缩放提高梯度下降的性能
工具
您将利用在上一个实验中开发的函数以及matplotlib和NumPy
import numpy as np
np.set_printoptions(precision=2)
import matplotlib.pyplot as plt
dlblue = '#0096ff'; dlorange = '#FF9300'; dldarkred='#C00000'; dlmagenta='#FF40FF'; dlpurple='#7030A0';
plt.style.use('./deeplearning.mplstyle')
from lab_utils_multi import load_house_data, compute_cost, run_gradient_descent
from lab_utils_multi import norm_plot, plt_contour_multi, plt_equal_scale, plot_cost_i_w
当前jupyter note工作目录需要包含:
概念
问题陈述
与之前的实验一样,您将使用房价预测的激励示例。训练数据集包含许多具有4个特征(大小,卧室,楼层和年龄)的示例,如下表所示。注意,在本实验中,尺寸特征以平方英尺为单位,而早期的实验室使用1000平方英尺。这个数据集比以前的实验室要大。
我们想用这些值建立一个线性回归模型,这样我们就可以预测其他房子的价格——比如,一栋1200平方英尺、3间卧室、1层、40年的房子。
数据集
# load the dataset
X_train, y_train = load_house_data()
X_features = ['size(sqft)','bedrooms','floors','age']
data里面需要包含house.txt
让我们通过绘制每个特征与价格的关系来查看数据集及其特征。
fig,ax=plt.subplots(1, 4, figsize=(12, 3), sharey=True)
for i in range(len(ax)):ax[i].scatter(X_train[:,i],y_train)ax[i].set_xlabel(X_features[i])
ax[0].set_ylabel("Price (1000's)")
plt.show()
将每个特征与目标价格进行对比,可以显示哪些特征对价格的影响最大。以上,增大尺寸也增加价格。卧室和楼层似乎对房价没有太大影响。新房子的价格比旧房子高。
多变量梯度下降
学习率
讲座讨论了与设置学习率相关的一些问题。学习率控制参数更新的大小。见式(1)。它由所有参数共享。让我们运行梯度下降并在我们的数据集上尝试一些a的设置
a=9.9e-7
#set alpha to 9.9e-7
_, _, hist = run_gradient_descent(X_train, y_train, 10, alpha = 9.9e-7)
看来学习率太高了。解不收敛。损失Cost在增加而不是减少(Cost列)。让我们来绘制结果:
plot_cost_i_w(X_train, y_train, hist)
右图显示了其中一个参数的值。在每次迭代中,它都会超过最优值,因此,损失Cost最终会增加而不是接近最小值。请注意,这不是一个完全准确的图片,因为每次有4个参数被修改,而不仅仅是一个。该图仅显示w[0],其他参数固定在良性值。在这个和后面的图中,你可能会注意到蓝色和橙色的线稍微偏离了。
a=9e-7
我们试试小一点的值,看看会发生什么。
#set alpha to 9e-7
_,_,hist = run_gradient_descent(X_train, y_train, 10, alpha = 9e-7)
损失Cost在整个运行过程中不断下降,这表明alpha不是太大。
plot_cost_i_w(X_train, y_train, hist)
在左边,你可以看到成本在下降。在右边,你可以看到,wo仍然在最小值附近振荡,但它每个都在减小迭代而不是增加。注意,dj_dw[0]随着每次迭代而改变符号,因为w[0]跳过了最优值。这个值会收敛。您可以改变迭代的次数来查看它的行为。
a=1e-7
我们试试小一点的α值,看看会发生什么。
#set alpha to 1e-7
_,_,hist = run_gradient_descent(X_train, y_train, 10, alpha = 1e-7)
成本在整个运行过程中不断下降,表明α不是太大。
plot_cost_i_w(X_train,y_train,hist)
在左边,你可以看到成本在下降。在右边你可以看到,在没有超过最小值的情况下,wo在增加。上面请注意Dj_wo在整个运行过程中为负。这个解决方案也会收敛,尽管没有前面的示例那么快。
特征缩放
讲座描述了重新缩放数据集的重要性,以便特征有相似的范围。
讲座讨论了三种不同的技巧:
- 特征缩放,本质上是将每个特征除以用户选择的值,得到一个介于-1和1之间的范围。
- 均值归一化
- z分数归一化,我们将在下面探讨。
在z-score归一化之后,所有特征的均值为0,标准差为1。要实现z-score归一化,调整输入值,如下公式所示:
实现注意:在对特征进行归一化时,存储用于归一化的值是很重要的——用于计算的平均值和标准偏差。在从模型中学习参数之后,我们经常想要预测我们之前没有见过的房子的价格。给定一个新的x值(客厅面积和卧室数量),我们必须首先使用我们之前从训练集中计算的平均值和标准差对x进行规范化。
实现
def zscore_normalize_features(X):"""computes X, zcore normalized by columnArgs:X (ndarray): Shape (m,n) input data, m examples, n featuresReturns:X_norm (ndarray): Shape (m,n) input normalized by columnmu (ndarray): Shape (n,) mean of each featuresigma (ndarray): Shape (n,) standard deviation of each feature"""# find the mean of each column/featuremu = np.mean(X, axis=0) # mu will have shape (n,)# find the standard deviation of each column/featuresigma = np.std(X, axis=0) # sigma will have shape (n,)# element-wise, subtract mu for that column from each example, divide by std for that columnX_norm = (X - mu) / sigma return (X_norm, mu, sigma)#check our work
#from sklearn.preprocessing import scale
#scale(X_orig, axis=0, with_mean=True, with_std=True, copy=True)
让我们看看z分数归一化的步骤。下面的图一步一步地展示了这个转换。
mu = np.mean(X_train,axis=0)
sigma = np.std(X_train,axis=0)
X_mean = (X_train - mu)
X_norm = (X_train - mu)/sigma fig,ax=plt.subplots(1, 3, figsize=(12, 3))
ax[0].scatter(X_train[:,0], X_train[:,3])
ax[0].set_xlabel(X_features[0]); ax[0].set_ylabel(X_features[3]);
ax[0].set_title("unnormalized")
ax[0].axis('equal')ax[1].scatter(X_mean[:,0], X_mean[:,3])
ax[1].set_xlabel(X_features[0]); ax[0].set_ylabel(X_features[3]);
ax[1].set_title(r"X - $\mu$")
ax[1].axis('equal')ax[2].scatter(X_norm[:,0], X_norm[:,3])
ax[2].set_xlabel(X_features[0]); ax[0].set_ylabel(X_features[3]);
ax[2].set_title(r"Z-score normalized")
ax[2].axis('equal')
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
fig.suptitle("distribution of features before, during, after normalization")
plt.show()
上图显示了两个训练集参数“age”和“sqft”之间的关系。这些是用等比尺绘制的。
- 左:未归一化:“大小(平方英尺)”特征的值范围或方差比年龄大得多
- 中间:第一步find从每个中移除平均值或平均值特性。这就留下了以零为中心的特征。很难看出“年龄”特征的区别,但“尺寸(平方英尺)”明显接近于零。
- 右:第二步除以方差。这使得两个特征都以相似的比例居中于零。
让我们对数据进行标准化,并将其与原始数据进行比较。
# normalize the original features
X_norm, X_mu, X_sigma = zscore_normalize_features(X_train)
print(f"X_mu = {X_mu}, \nX_sigma = {X_sigma}")
print(f"Peak to Peak range by column in Raw X:{np.ptp(X_train,axis=0)}")
print(f"Peak to Peak range by column in Normalized X:{np.ptp(X_norm,axis=0)}")
通过归一化,每列的峰到峰范围从千的因数减少到2-3的因数。
fig,ax=plt.subplots(1, 4, figsize=(12, 3))
for i in range(len(ax)):norm_plot(ax[i],X_train[:,i],)ax[i].set_xlabel(X_features[i])
ax[0].set_ylabel("count");
fig.suptitle("distribution of features before normalization")
plt.show()
fig,ax=plt.subplots(1,4,figsize=(12,3))
for i in range(len(ax)):norm_plot(ax[i],X_norm[:,i],)ax[i].set_xlabel(X_features[i])
ax[0].set_ylabel("count");
fig.suptitle(f"distribution of features after normalization")plt.show()
注意,上面的归一化数据的范围以0为中心,大致为+/-1。最重要的是,每个特性的范围是相似的。让我们用规范化数据重新运行梯度下降算法。注意,alpha的值要大得多。这将加速下降。
w_norm, b_norm, hist = run_gradient_descent(X_norm, y_train, 1000, 1.0e-1, )
缩放的特征得到非常准确的结果,快得多!注意,在这个相当短的运行结束时,每个参数的梯度都很小。对于使用归一化特征的回归来说,学习率为0.1是一个良好的开端。让我们根据目标值绘制出预测结果。注意,预测是使用归一化特征进行的,而图是使用原始特征值显示的。
#predict target using normalized features
m = X_norm.shape[0]
yp = np.zeros(m)
for i in range(m):yp[i] = np.dot(X_norm[i], w_norm) + b_norm# plot predictions and targets versus original features
fig,ax=plt.subplots(1,4,figsize=(12, 3),sharey=True)
for i in range(len(ax)):ax[i].scatter(X_train[:,i],y_train, label = 'target')ax[i].set_xlabel(X_features[i])ax[i].scatter(X_train[:,i],yp,color=dlorange, label = 'predict')
ax[0].set_ylabel("Price"); ax[0].legend();
fig.suptitle("target versus prediction using z-score normalized model")
plt.show()
结果看起来不错。
有几点需要注意:
- 有了多个特征,我们就不能再用一个图来显示结果和特征了。
- 在生成图时,使用归一化特征。使用从规范化训练集中学习到的参数的任何预测也必须规范化,生成模型的目的是用它来预测数据集中没有的房价。
让我们来预测一套1200平方英尺、3间卧室、1层、40年历史的房子的价格。回想一下,当训练数据被归一化时,必须使用得到的均值和标准差对数据进行归一化。
# First, normalize out example.
x_house = np.array([1200, 3, 1, 40])
x_house_norm = (x_house - X_mu) / X_sigma
print(x_house_norm)
x_house_predict = np.dot(x_house_norm, w_norm) + b_norm
print(f" predicted price of a house with 1200 sqft, 3 bedrooms, 1 floor, 40 years old = ${x_house_predict*1000:0.0f}")
成本轮廓另一种查看特征缩放的方法是根据成本轮廓。当特征尺度不匹配时,等值线图中成本与参数的关系是不对称的。在下面的图中,参数的比例是匹配的。左边的图是在特征归一化之前w[0](平方英尺与w1的成本等高线图。这个图是如此不对称,完成等高线的曲线是不可见的。相比之下,当特征归一化时,成本轮廓更加对称。结果是,在梯度下降过程中对参数的更新可以使每个参数取得相同的进展。
plt_equal_scale(X_train, X_norm, y_train)
恭喜
在这个实验中,你
- 利用您在以前的实验中开发的具有多个特性的线性回归例程
- 探讨了学习率a对收敛的影响
- 发现使用z-score归一化的特征缩放在加速收敛方面的价值
致谢
住房数据来源于Dean De Cock为数据科学教育编制的Ames住房数据集。