波士顿房价预测

波士顿房价预测是一个经典的机器学习任务,期待构建一个房价预测模型,其数据中包含13个影响房价的因素和该类型房屋均价。

波士顿房价影响因素

数据预处理

数据预处理包括:

  • 数据导入

  • 数据形状变换

  • 数据集划分:将数据集划分为训练集与测试集

  • 数据归一化:归一化主要的目的是将所有因素的数据转换到相同的范围内,便于设置相同的学习率。

 1import numpy as np 2 3# 数据集下载位置: 4# https://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.data 5# 加载数据集 6data = np.fromfile('./data/housing.data', sep=' ') 7 8# 数据形状转换,转换为N*14个格式 9# 每14个元素为一个数据,前13个为相应的特征,最后一个为均价10feature_names = [ 'CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE','DIS', 11                 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV' ]12feature_num = len(feature_names)13print('old shape',data.shape)14data = data.reshape(data.shape[0]//feature_num,feature_num)15print('new shape',data.shape)1617# 将原数据集拆分成训练集和测试集18# 这里使用80%的数据做训练,20%的数据做测试19# 测试集和训练集必须是没有交集的20ratio = 0.821offset = int(data.shape[0] * ratio)22training_data = data[:offset]23test_data = data[offset:]24print("training_data shape",training_data.shape)25print("test_data shape",test_data.shape)2627# 计算训练集的最大值,最小值,平均值28# 测试集归一化时采用的是训练集的最大、最小值29# 测试数据尽量拟合真实样本,但真实世界的样本范围无法获取30# 因此拟合时,采用训练集的最值进行归一化31maximums, minimums, avgs = \32    data.max(axis=0), \33    data.min(axis=0), \34    data.sum(axis=0) / data.shape[0]3536# 数据归一化,将特征值取值范围转换到0-1之间37# 这样做有两个好处:38# 一是模型训练更高效;39# 二是特征前的权重大小可以代表该变量对预测结果的贡献度(因为每个特征值本身的范围相同)。40# 便于设置学习率41for i in range(feature_num):42    data[:, i] = (data[:, i] - minimums[i]) / (maximums[i] - minimums[i])434445print(data[0])
1old shape (7084,)2new shape (506, 14)3training_data shape (404, 14)4test_data shape (102, 14)5[0.         0.18       0.06781525 0.         0.31481481 0.577505276 0.64160659 0.26920314 0.         0.20801527 0.28723404 1.7 0.08967991 0.42222222]

以上步骤可以封装为一个函数load_data,便于调用。

 1import numpy as np 2 3max_values = 0 4min_values = 0 5avg_values = 0  6def load_data(): 7    # 数据集下载位置: 8    # https://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.data 9    # 数据集导入10    data = np.fromfile('./data/housing.data', sep=' ')1112    # 数据形状变换13    feature_names = [ 'CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE','DIS', 14                     'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV' ]15    feature_num = len(feature_names)16    data = data.reshape(data.shape[0]//feature_num,feature_num)1718    # 数据集划分19    ratio = 0.820    offset = int(data.shape[0] * ratio)21    training_data = data[:offset]22    test_data = data[offset:]2324    global max_values 25    global min_values 26    global avg_values 27    # 数据归一化28    max_values, min_values, avg_values = \29        data.max(axis=0), \30        data.min(axis=0), \31        data.sum(axis=0) / data.shape[0]3233    for i in range(feature_num):34        data[:, i] = (data[:, i] - min_values[i]) / (max_values[i] - min_values[i])3536    training_data = data[:offset]37    test_data = data[offset:]38    return training_data, test_data

模型假设

对于预测问题,可根据预测值类型为连续还是离散值,分为回归任务和分类任务。由于房价是连续值,因此属于回归任务,可以采用线性回归解决问题。

线性回归模型可被视作为只有加权和,没有非线性变换的神经元。

线性回归模型的神经网络结构
 1np.random.seed(0) 2# 随机生成参数权重和偏置 3w = np.random.randn(13,1) 4b = 0. 5# 取出第一条数据的参数 6x = data[0,:-1] 7y = data[0,-1] 8 9# 线性回归10z = np.dot(x,w) + b11print('real',y)12print('predict:',z)
1real 0.42222222222222222predict: [2.38009889]
 1class Network(object): 2    def __init__(self, num_of_weights): 3        # 随机产生w的初始值 4        # 为了保持程序每次运行结果的一致性, 5        # 此处设置固定的随机数种子 6        np.random.seed(0) 7        self.w = np.random.randn(num_of_weights, 1) 8        self.b = 0. 910    def forward(self, x):11        z = np.dot(x, self.w) + self.b12        return z1314net = Network(13)15z = net.forward(x)16print('predict:',z)
1predict: [2.38009889]

效果评估

这里采用均方误差作为损失函数

 1class Network(object): 2    def __init__(self, num_of_weights): 3        np.random.seed(0) 4        self.w = np.random.randn(num_of_weights, 1) 5        self.b = 0. 6 7    def forward(self, x): 8        z = np.dot(x, self.w) + self.b 9        return z1011    def loss(self, z, y):12        error = z - y13        cost = error * error14        cost = np.mean(cost)15        return cost1617net = Network(13)18z = net.forward(x)19print("loss:",net.loss(z,y))
1loss: 3.8332810388860867

优化

深度学习的目标是让损失函数Loss尽可能小,换句话说,找到一个参数解和,使损失函数取极小值。

函数导数

上图中,函数在处的梯度方向沿黄线向上,因此要取极小值的点P_x,则需要沿着梯度的反方向移动,直到梯度值为0为止。

那么损失函数为什么要选择均方误差而不选择绝对值误差呢?

均方误差和绝对值误差损失函数曲线图

原因有两点:

  • 绝对值误差在极小值点不可微分,均分误差可微

  • 绝对值误差在接近极小值点时,梯度值不变;而均分误差梯度值在变小,有助于调整移动步长,避免错过极小值点。

因此我们可以推导出梯度计算的方式:

预测值:

损失值(添加因子,主要为了方便计算偏导数):

梯度的定义:

可以计算出对和的偏导数:

计算出梯度后,我们可以沿着梯度的反方向移动,更新参数。
这里就体现了归一化的重要性,如果不进行归一化,则需要设计对于的学习率。

归一化前后数据分布
 1class Network(object): 2    def __init__(self, num_of_weights): 3        np.random.seed(0) 4        self.w = np.random.randn(num_of_weights, 1) 5        self.b = 0. 6 7    def forward(self, x): 8        """前向传播""" 9        z = np.dot(x, self.w) + self.b10        return z1112    def loss(self, z, y):13        """计算损失值"""14        error = z - y15        num_samples = error.shape[0]16        cost = error * error17        cost = np.sum(cost) / num_samples18        return cost1920    def gradient(self, x, y):21        """计算梯度"""22        z = self.forward(x)23        gradient_w = (z-y)*x24        gradient_w = np.mean(gradient_w, axis=0)25        gradient_w = gradient_w[:, np.newaxis]26        gradient_b = (z - y)27        gradient_b = np.mean(gradient_b)        28        return gradient_w, gradient_b2930    def update(self, gradient_w, gradient_b, eta = 0.01):31        """更新梯度"""32        self.w = self.w - eta * gradient_w33        self.b = self.b - eta * gradient_b3435    def train(self, x, y, iterations=100, eta=0.01):36        """训练"""37        losses = []38        for i in range(iterations):39            z = self.forward(x)40            L = self.loss(z, y)41            gradient_w, gradient_b = self.gradient(x, y)42            self.update(gradient_w, gradient_b, eta)43            losses.append(L)44#             if (i+1) % 10 == 0:45#                 print('iter {}, loss {}'.format(i, L))46        return losses
 1import matplotlib.pyplot as plt 2# 获取数据 3train_data, test_data = load_data() 4x = train_data[:, :-1] 5y = train_data[:, -1:] 6# 创建网络 7net = Network(13) 8num_iterations=1000 9# 启动训练10losses = net.train(x,y, iterations=num_iterations, eta=0.01)1112# 画出损失函数的变化趋势13plot_x = np.arange(num_iterations)14plot_y = np.array(losses)15plt.plot(plot_x, plot_y)16plt.show()

loss

随机梯度下降法

上诉程序中,每次损失函数和梯度计算都基于全量数据,当数据集非常大时,效率非常低。随机梯度下降法SGD采用从数据集中随机抽取小部分数据,基于这部分数据,计算梯度和损失,并更新参数。

  • mini-batch:每次迭代时抽取出来的数据。

  • batch_size:一个mini-batch所包含样本数目。

  • epoch:数据集完成一次遍历,则为一个epoch。

 1import numpy as np 2 3class Network(object): 4    def __init__(self, num_of_weights): 5        np.random.seed(0) 6        self.w = np.random.randn(num_of_weights, 1) 7        self.b = 0. 8 9    def forward(self, x):10        z = np.dot(x, self.w) + self.b11        return z1213    def loss(self, z, y):14        error = z - y15        num_samples = error.shape[0]16        cost = error * error17        cost = np.sum(cost) / num_samples18        return cost1920    def gradient(self, x, y):21        z = self.forward(x)22        N = x.shape[0]23        gradient_w = 1. / N * np.sum((z-y) * x, axis=0)24        gradient_w = gradient_w[:, np.newaxis]25        gradient_b = 1. / N * np.sum(z-y)26        return gradient_w, gradient_b2728    def update(self, gradient_w, gradient_b, eta = 0.01):29        self.w = self.w - eta * gradient_w30        self.b = self.b - eta * gradient_b313233    def train(self, training_data, num_epoches, batch_size=10, eta=0.01):34        n = len(training_data)35        losses = []36        for epoch_id in range(num_epoches):37            # 在每轮迭代开始之前,将训练数据的顺序随机打乱38            # 然后再按每次取batch_size条数据的方式取出39            np.random.shuffle(training_data)40            # 将训练数据进行拆分,每个mini_batch包含batch_size条的数据41            mini_batches = [training_data[k:k+batch_size] for k in range(0, n, batch_size)]42            for iter_id, mini_batch in enumerate(mini_batches):43                #print(self.w.shape)44                #print(self.b)45                x = mini_batch[:, :-1]46                y = mini_batch[:, -1:]47                a = self.forward(x)48                loss = self.loss(a, y)49                gradient_w, gradient_b = self.gradient(x, y)50                self.update(gradient_w, gradient_b, eta)51                losses.append(loss)5253        return losses5455# 获取数据56train_data, test_data = load_data()5758# 创建网络59net = Network(13)60# 启动训练61losses = net.train(train_data, num_epoches=50, batch_size=100, eta=0.1)6263# 画出损失函数的变化趋势64plot_x = np.arange(len(losses))65plot_y = np.array(losses)66plt.plot(plot_x, plot_y)67plt.show()

loss

通过上图,我们可以观察到,随机梯度下降加速了训练过程,但由于每次基于的样本数较少,损失下降曲线会出现震荡。

采用飞桨重构模型

重构主要使用如下库:

  • paddle/fluid:飞桨的主库,目前大部分的实用函数均在paddle.fluid包内。

  • dygraph:动态图的类库。

  • Linear:全连接层函数,包含所有输入权重相加和激活函数的基本神经元结构。

飞桨支持两种深度学习建模编写方式:

  • 静态图:类似C++,需要先编译后执行。该模式通常用于部署。

  • 动态图:类似Python,每写一行网络代码,即可同时获得计算结果。该模式通常用于调试。

 1#加载飞桨、Numpy和相关类库 2import paddle 3import paddle.fluid as fluid 4# dygraph:动态图的类库 5import paddle.fluid.dygraph as dygraph 6# 神经网络的全连接层函数 7from paddle.fluid.dygraph import Linear 8import numpy as np 9import os10import random1112class Regressor(fluid.dygraph.Layer):13    def __init__(self):14        super(Regressor, self).__init__()15        # 定义一层全连接层,输出维度是1,不使用激活函数16        self.fc = Linear(input_dim=13, output_dim=1, act=None)1718    def forward(self, inputs):19        # 前向计算20        x = self.fc(inputs)21        return x2223# 设置工作模式为动态图,使用CPU计算24with dygraph.guard(fluid.CPUPlace()):    25    # 声明定义好的线性回归模型26    model = Regressor()2728    # 开启模型训练模式29    model.train()3031    # 加载数据32    training_data, test_data = load_data()3334    # 定义优化算法,这里使用随机梯度下降-SGD35    # 学习率设置为0.0136    opt = fluid.optimizer.SGD(learning_rate=0.01, parameter_list=model.parameters())3738    EPOCH_NUM = 10   # 设置外层循环次数39    BATCH_SIZE = 10  # 设置batch大小4041    # 外层循环42    for epoch_id in range(EPOCH_NUM):43        # 在每轮迭代开始之前,将训练数据的顺序随机的打乱44        np.random.shuffle(training_data)45        # 将训练数据进行拆分,每个batch包含10条数据46        mini_batches = [training_data[k:k+BATCH_SIZE] for k in range(0, len(training_data), BATCH_SIZE)]47        # 定义内层循环48        for iter_id, mini_batch in enumerate(mini_batches):49            x = np.array(mini_batch[:, :-1]).astype('float32') # 获得当前批次训练数据50            y = np.array(mini_batch[:, -1:]).astype('float32') # 获得当前批次训练标签(真实房价)5152            # 将numpy数据转为飞桨动态图variable形式53            house_features = dygraph.to_variable(x)54            prices = dygraph.to_variable(y)5556            # 前向计算57            predicts = model(house_features)5859            # 计算损失60            loss = fluid.layers.square_error_cost(predicts, label=prices)61            avg_loss = fluid.layers.mean(loss)62#             if iter_id%20==0:63#                 print("epoch: {}, iter: {}, loss is: {}".format(epoch_id, iter_id, avg_loss.numpy()))6465            # 反向传播66            avg_loss.backward()67            # 最小化loss,更新参数68            opt.minimize(avg_loss)69            # 清除梯度70            model.clear_gradients()71    # 保存模型72    fluid.save_dygraph(model.state_dict(), 'LR_model')7374# 模型测试75with dygraph.guard():76    # 参数为保存模型参数的文件地址77    model_dict, _ = fluid.load_dygraph('LR_model')78    model.load_dict(model_dict)79    # 进入预测模式,只支持前向计算80    model.eval()8182    # 将数据转为动态图的variable格式83    data = np.array(test_data[:, :-1]).astype('float32') # 测试数据84    labels = np.array(test_data[:, -1:]).astype('float32') # 测试标签(真实房价)8586    test = dygraph.to_variable(data[0])87    result = model(test)8889    # 对结果做反归一化处理90    result = result * (max_values[-1] - min_values[-1]) + avg_values[-1]91    label = labels[0] * (max_values[-1] - min_values[-1]) + avg_values[-1]92    print("Inference result is {}, the corresponding label is {}".format(result.numpy(), label))
1Inference result is [29.837013], the corresponding label is [26.032806]

统计学习基础:数据挖掘、推理和预测_百度零基础深度学习笔记(三) 波士顿房价预测...相关推荐

  1. pytorch神经网络因素预测_实战:使用PyTorch构建神经网络进行房价预测

    微信公号:ilulaoshi / 个人网站:lulaoshi.info 本文将学习一下如何使用PyTorch创建一个前馈神经网络(或者叫做多层感知机,Multiple-Layer Perceptron ...

  2. 零基础深度学习对金县房价预测

    这里写目录标题 一.深度学习 1.1 基本概念 1.2 概念详细介绍 二.金县房价预测 2.1 导入数据 2.2 训练模型 2.3 验证结果 三.参考资料 一.深度学习 1.1 基本概念 所有的机器学 ...

  3. 利用神经网络进行波士顿房价预测

    前言 ​    前一阵学校有五一数模节校赛,和朋友一起参加做B题,波士顿房价预测,算是第一次自己动手实现一个简单的小网络吧,虽然很简单,但还是想记录一下. 题目介绍 ​    波士顿住房数据由哈里森和 ...

  4. 【机器学习】P25 随机森林算法(2) 实现 “波士顿房价” 预测

    随机森林算法 Random Forest Algorithm 随机森林算法 随机森林算法实现波士顿房价预测 随机森林算法 随机森林(Random Forest)算法 是一种 集成学习(Ensemble ...

  5. 使用Python和Numpy进行波士顿房价预测任务(二)【深度学习入门_学习笔记】

    使用Python和Numpy进行波士顿房价预测任务–详解 目录: 一.数据处理 (1)读入数据 (2)数据形状变换 (3)数据集划分 (4)数据归一化处理 (5)封装成load data函数 二.模型 ...

  6. MOOC网深度学习应用开发1——Tensorflow基础、多元线性回归:波士顿房价预测问题Tensorflow实战、MNIST手写数字识别:分类应用入门、泰坦尼克生存预测

    Tensorflow基础 tensor基础 当数据类型不同时,程序做相加等运算会报错,可以通过隐式转换的方式避免此类报错. 单变量线性回归 监督式机器学习的基本术语 线性回归的Tensorflow实战 ...

  7. 使用Python和Numpy进行波士顿房价预测任务(一)【深度学习入门_学习笔记】

    波士顿房价预测是一个经典的机器学习任务,类似于程序员世界的"Hello World".和大家对房价的普遍认知相同,波士顿地区的房价是由诸多因素影响的. 下载数据集:https:// ...

  8. 深度学习入门——波士顿房价预测

    基于神经网络模型的波士顿房价预测 波士顿房价预测是一个经典的机器学习任务,类似于程序员世界的"Hello World".以"波士顿房价预测"任务为例,我们学习如 ...

  9. 深度学习经典入门项目—波士顿房价预测

    目录 房价预测--线性回归 数据处理 数据形状变换 数据集划分 数据归一化处理 housing.data数据格式 模型设计 线性回归模型设计 训练配置 训练过程 保存并测试模型 保存模型 测试模型 房 ...

最新文章

  1. 清华计算机本硕博连读!中国籍袁昱博士当选2022年IEEE标准协会候任主席
  2. php删除数组中指定值的元素
  3. linux 系统管理命令整理
  4. perl 对ENV环境变量的使用
  5. 19.Extjs主页面显示js
  6. android文件管理实现所应用到的技术,基于Android的文件管理系统的设计与实现
  7. hash算法_数据库中间件分片算法之hash
  8. mysql取最大一条数据,mysql取出表中,某字段值最大的一条纪录,sql语句
  9. 最近都在谈的「私域流量」,究竟有没有前途?
  10. CVPR2019 Oral!伯克利、麻省理工GAN图像合成最新成果(附开源代码)!
  11. react-生命周期
  12. 支持IE,Firefox的日历控件
  13. Python logging日志系统
  14. ICPC North Central NA Contest 2017 E - Is-A? Has-A? Who Knowz-A?
  15. java-Socket文件传输
  16. 水泥电阻,常用电阻 阻值表
  17. 【最全攻略】拼多多商家自研系统接入流程
  18. 史上最全的数据链路层基础知识详解
  19. Server2008如何卸载MySQL_「完美卸载」完美卸载SQL Server 2008 R2 的方法,适合所有问题 - seo实验室...
  20. 520送什么蓝牙耳机好?高颜值高性价比的无线蓝牙耳机推荐

热门文章

  1. C语言累加函数代码,ARM汇编程序---通过ARM汇编调用C语言函数实现累加
  2. android伸缩动画,Android 伸缩动画xml配置
  3. 带经纬度的水印相机_这个国庆节,元道经纬相机做交警人员的好帮手
  4. asp.net+sql数据库学生信息管理系统
  5. HDU 4371 Alice and Bob
  6. WCF学习之旅(一)---Hello World.
  7. 单、双链表的循环链表(十五)
  8. EasyConnect for Linux
  9. Android Studio GPU/CPU/Network/Memory monitor使用
  10. Android4.4 多媒体开发(五)----OpenMax简介