大连市城乡建设厅网站,windows永久禁止更新,笔记wordpress,廉政建设网评文章网站波士顿房价预测
目标
这是一个经典的机器学习回归场景#xff0c;我们利用Python和numpy来实现神经网络。该数据集统计了房价受到13个特征因素的影响#xff0c;如图1所示。 对于预测问题#xff0c;可以根据预测输出的类型是连续的实数值#xff0c;还是离散值#xff…波士顿房价预测
目标
这是一个经典的机器学习回归场景我们利用Python和numpy来实现神经网络。该数据集统计了房价受到13个特征因素的影响如图1所示。 对于预测问题可以根据预测输出的类型是连续的实数值还是离散值区分是回归还是分类问题。**因为房价是一个连续值这是一个回归任务。**下面利用简单的线性回归来解决这个问题并利用神经网络来实现这个模型。
线性回归模型
假设房价和各个影像因素之间的函数关系是 y∑j1Mxjwjby \sum_{j1}^{M}x_jw_j by∑j1Mxjwjb 模型的目标就是通过拟合数据来求出wjw_jwj和bbb两个参数。线性回归模型采用均方误差MSE损失函数LossLossLoss,用以衡量预测房价和真实值的差异公式
MSE1N∑i1N(Yi∧−Yi)2MSE\frac{1}{N}\sum_{i1}{N}(Y_i^{\wedge} - Y_i)^2MSEN1∑i1N(Yi∧−Yi)2
思考为什么要以均方误差为损失函数考虑到便于求解。
线性回归的神经网络结构
神经网络结构就是一个个神经元加层来组成。线性回归认为是神经网络模型的一种简单特例是一个只有加权求和没有非线性变换的神经元如图2:。 两层神经网络 深度学习不仅实现了模型的端到端学习还推动了人工智能进入工业大生产阶段产生了标准化、自动化和模块化的通用框架。不同场景的深度学习模型具备一定的通用性五个步骤即可完成模型的构建和训练。如图3所示。 ### 数据处理
数据探查
import numpy as np
import json
# 读入训练数据
datafile ./work/housing.data
data np.fromfile(datafile, sep )数据变形
feature_names [ CRIM, ZN, INDUS, CHAS, NOX, RM, AGE,DIS, RAD, TAX, PTRATIO, B, LSTAT, MEDV ]
feature_num len(feature_names)
data data.reshape([data.shape[0] // feature_num, feature_num])
print(data.shape) # 将数据做了转化样本总数是506个样本划分数据集 将数据集划分训练集和测试集训练集用于确定模型的参数测试集用于评估模型的效果。图5 上学时总有一些自作聪明的同学平时不认真学习考试前临阵抱佛脚将习题死记硬背下来但是成绩往往并不好。因为学校期望学生掌握的是知识而不仅仅是习题本身。另出新的考题才能鼓励学生努力去掌握习题背后的原理。同样我们期望模型学习的是任务的本质规律而不是训练数据本身模型训练未使用的数据才能更真实的评估模型的效果。
# 数据集划分操作
ratio 0.8
offset int(data.shape[0] * ratio)
training_data data[:offset]
training_data.shape
# print(data.shape)数据集归一化 利用最大值最小值归一方法使得每个特征的值都是被缩放到[0,1]之间这样做的好处有1、模型训练更加高效特征前的权重大小可以代表该变量对预测结果的贡献度。
maximums, minimums \training_data.max(axis0), \training_data.min(axis0),
# 对数据进行归一化处理
for i in range(feature_num):data[:, i] (data[:, i] - minimums[i]) / (maximums[i] - minimums[i])将上述过程封装为函数
def load_data():# 从文件导入数据datafile ./work/housing.datadata np.fromfile(datafile, sep )# 每条数据包括14项其中前面13项是影响因素第14项是相应的房屋价格中位数feature_names [ CRIM, ZN, INDUS, CHAS, NOX, RM, AGE, \DIS, RAD, TAX, PTRATIO, B, LSTAT, MEDV ]feature_num len(feature_names)# 将原始数据进行Reshape变成[N, 14]这样的形状data data.reshape([data.shape[0] // feature_num, feature_num])# 将原数据集拆分成训练集和测试集# 这里使用80%的数据做训练20%的数据做测试# 测试集和训练集必须是没有交集的ratio 0.8offset int(data.shape[0] * ratio)training_data data[:offset]# 计算训练集的最大值最小值maximums, minimums training_data.max(axis0), \training_data.min(axis0)# 对数据进行归一化处理for i in range(feature_num):data[:, i] (data[:, i] - minimums[i]) / (maximums[i] - minimums[i])# 训练集和测试集的划分比例training_data data[:offset]test_data data[offset:]return training_data, test_data
获取数据
# 获取数据
training_data, test_data load_data()
x training_data[:, :-1]
y training_data[:, -1:] # 实际值模型设计
一层神经网络设计
模型的设计是深度学习模型关键要素之一称为网络结构。相当于模型的假设空间既是实现模型的“前向计算”从输入到输出过程。 如果将输入和输出都用向量表示输入特征x有13个向量y有1个向量。那么权重参数就是13*1。
w [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, -0.1, -0.2, -0.3, -0.4, 0.0] #第一层的权重参数
w_t np.array(w).reshape([13, 1]) # 相当于矩阵的转置
w_t.shape
# 一个特征列就是一个向量假设第一个样本x[0]和一层神经网络进行运算。yx.wTyx.w^Tyx.wT运算逻辑。其中x[0]x1,x2,...x13x[0]{x_1,x_2,...x_{13}}x[0]x1,x2,...x13x [0]的shape是1,13,wTw^TwT的维度是(13,1)刚好满足两个矩阵乘法的运算原则。
x1x[0] #获取第一个样本
print(x1.shape)
t np.dot(x1, w_t)
print(t.shape)
# 我们发现样本的特征向量与参数向量相乘的结果是scaler。
# 矩阵的乘法1,13(13,1) A*B其中A的列要和B的行相等才可进行矩阵的乘法运算。
b -0.2
z t b
print(z)完整的线性回归计算公式是:ztbztbztbb是初始化偏移量以上从特征[0]到计算输出值的过程就是“前向计算”。 定义一个类方便后面调用
class MyNetwork(object):def __init__(self, num_of_weights):np.random.seed(0)self.w np.random.randn(num_of_weights,1)self.b 0.def forward_m(self,x):# 表示的是前向计算res np.dot(x,self.w) self.breturn res二层神经网络
定义两层的神经网络其中需要注意的地方输入数据是直接和第一层进行x.wTx.w^Tx.wT运算第一层每个神经元的输出则是做为第二层每个神经元的输入x。那么在第二层神经运算是w.xw.xw.x就是对应位置元素相乘[x11.w11,x12.w12,x13.w13,...x113.w113][ x_1^1.w_1^1,x_1^2.w_1^2,x_1^3.w_1^3,...x_1^{13}.w_1^{13}][x11.w11,x12.w12,x13.w13,...x113.w113]在与第二层的权值参数w2w_2w2进行运算。
# 定义两层神经网络输出
class My2Network(object):def __init__(self, num_of_weights):np.random.seed(0)# 两层神经网络共享权值w self.w np.random.randn(num_of_weights,1)self.ww np.random.randn(num_of_weights,1)self.b 0.def forword(self,x):# 前向计算有两层神经网络z_1 np.dot(x,self.w)# 计算第一层输出做为第二层的输入out_1 self.w.reshape([1,13]) * xz_2 np.dot(out_1,self.ww)return z_1 z_2 self.b训练配置
模型设计完成后需要通过训练配置寻找模型的最优值即通过损失函数来衡量模型的好坏。训练配置也是深度学习模型关键要素之一。 通过模型计算x1x_1x1表示的影响因素所对应的房价应该是z, 但实际数据告诉我们房价是y。这时我们需要有某种指标来衡量预测值z跟真实值y之间的差距。对于回归问题最常采用的衡量方法是使用均方误差作为评价模型好坏的指标公式为: Loss(y−z)2Loss (y-z)^2Loss(y−z)2 Loss就是损失函数衡量模型好坏的指标。在回归问题中一般是均方误差作为损失函数而在分类问题中采用交叉熵作为损失函数。 x1x_1x1样本的损失
loss (y_1 - res_1)*(y_1-res_1)
print(loss)因为在计算损失函数需要把每个样本的损失函数得到求和在平均。 Loss1N∑i1N(yi−zi)2Loss\frac{1}{N}\sum_{i1}^{N}(y_i - z_i)^2LossN1∑i1N(yi−zi)2 在前Network类中增加loss函数。
class Network(object):def __init__(self, num_of_weights):# 随机产生w的初始值# 为了保持程序每次运行结果的一致性此处设置固定的随机数种子np.random.seed(0)self.w np.random.randn(num_of_weights, 1)self.b 0.def forward(self, x):z np.dot(x, self.w) self.breturn zdef loss(self, z, y):error z - ycost error * errorcost np.mean(cost)return cost训练过程
在模型的前面两部完成接下来就是求解参数wbwbwb的数值这就是模型训练的过程。求解w和b使得损失函数取得极小值。 eg.eg.eg. 下面给出一个微积分的案例一个曲线在某点的导数。导数等于在该点处的切线的斜率。 上图曲线在极值点处的斜率等于0既是函数的极值点。那么损失函数的取值为下面方程组的解 ∂L∂w0\frac{\partial L}{\partial w} 0∂w∂L0 ∂L∂b0\frac{\partial L}{\partial b} 0∂b∂L0 上述两个方程组的解就是最后模型训练获取到的参数。但是这种方法有个缺点当模型中含有非线性变换则不好计算。我们引入一种普世的方法——梯度下降法。
梯度下降算法 在现实中存在大量函数正向求解容易但是反向求解不容易被称为单向函数。神经网络的损失函数就是单向函数。 这种情况我们可以在现实生活中类比一个想从山峰走到山谷的盲人。他看不见山谷在哪儿无法逆向求解损失函数为0时的参数值但是可以伸出脚探索身边的坡度(当前点的导数梯度)。所以求解Loss的最小值过程就是在从当前参数取值一步步按照梯度的反方向下降。直到到达最低点。 下面。我们随机从损失函数中去参数w5,w9w_5,w_9w5,w9看看他们的变化情况。 LL(w5,w9)LL(w_5,w_9)LL(w5,w9) 我们将[w0,w1,...212][w_0,w_1,...2_{12}][w0,w1,...212]中除去w5,w9w_5,w_9w5,w9之前的参数和b全部固定下来。可以用图画出L(w5,w9)L(w_5,w_9)L(w5,w9)的形式。
net Network(13)
losses []
#只画出参数w5和w9在区间[-160, 160]的曲线部分以及包含损失函数的极值
w5 np.arange(-160.0, 160.0, 1.0)
w9 np.arange(-160.0, 160.0, 1.0)
losses np.zeros([len(w5), len(w9)])#计算设定区域内每个参数取值所对应的Loss
for i in range(len(w5)):for j in range(len(w9)):net.w[5] w5[i]net.w[9] w9[j]z net.forward(x)loss net.loss(z, y)losses[i, j] loss#使用matplotlib将两个变量和对应的Loss作3D图
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig plt.figure()
ax Axes3D(fig)w5, w9 np.meshgrid(w5, w9)ax.plot_surface(w5, w9, losses, rstride1, cstride1, cmaprainbow)
plt.show()观察上述曲线呈现出“圆滑”的坡度这正是我们选择以均方误差作为损失函数的原因之一。图6 呈现了只有一个参数维度时均方误差和绝对值误差只将每个样本的误差累加不做平方处理的损失函数曲线图。 由此可见均方误差表现的“圆滑”的坡度有两个好处
曲线在最低点出是可导的。越接近最低点曲线的坡度逐渐放缓有助于通过当前的梯度来判断接近最低点的程度是否逐渐减少步长以免错过最佳点。
然而绝对值误差事不具备的。这也是损失函数的设计不仅仅要考虑“合理性”还要追求“易解性”的原因。