深度学习——入门经典案例《波士顿房价预测》深度解析

2023-05-16

一、深度学习

机器学习算法理论在上个世纪90年代发展成熟,在许多领域都取得了成功应用。但平静的日子只延续到2010年左右,随着大数据的涌现和计算机算力提升,深度学习模型异军突起,极大改变了机器学习的应用格局。今天,多数机器学习任务都可以使用深度学习模型解决,尤其在在语音、计算机视觉和自然语言处理等领域,深度学习模型的效果比传统机器学习算法有显著提升。

有关机器学习、深度学习的详细介绍及其之间的联系可查看下方链接
https://www.paddlepaddle.org.cn/tutorials/projectdetail/328689

二、《波士顿房价预测》案例详解

项目完整代码和数据集已经上传,点击链接查看
https://github.com/Narutoooooooo/boston-house-price-forecast

  1. 前提说明

    数据详情:
    在这里插入图片描述
    构建波士顿房价预测任务的神经网络模型步骤:
    在这里插入图片描述

  2. 数据处理
    数据处理包含五个部分:数据导入、数据形状变换、数据集划分、数据归一化处理和封装load data函数。
    数据预处理后,才能被模型调用。

    数据归一化参考https://blog.csdn.net/program_developer/article/details/78637711

    实现代码如下:

    import numpy as np
    import matplotlib.pyplot as plt
    
    def load_data():
        # 读取以空格分开的文件,变成一个连续的数组
        firstdata = np.fromfile('housing.data', sep=' ')
        # 添加属性
        feature_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE', 'DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT',
                         'MEDV']
        # 列的长度
        feature_num = len(feature_names)
        # print(firstdata.shape)  输出结果:(7084, )
        # print(firstdata.shape[0] // feature_nums)  输出结果:506
        # 构造506*14的二维数组
        data = firstdata.reshape([firstdata.shape[0] // feature_num, feature_num])
    	
    	# 将数据集划分成训练集和测试集,其中训练集用于确定模型的参数,测试集用于评判模型的效果。
        # 训练集设置为总数据的80%
        ratio = 0.8
        offset = int(data.shape[0] * ratio)
        training_data = data[:offset]
        # print(training_data.shape)
    
        # axis=0表示列
        # axis=1表示行
        # \表示换行,无需输入
        maximums, minimums, avgs = training_data.max(axis=0), training_data.min(axis=0), training_data.sum(axis=0) / \
                                   training_data.shape[0]
        # 查看训练集每列的最大值、最小值、平均值
        # print(maximums, minimums, avgs)
    
        # 对所有数据进行归一化处理
        for i in range(feature_num):
            # print(maximums[i], minimums[i], avgs[i])
            # 归一化,减去平均值是为了移除共同部分,凸显个体差异
            data[:, i] = (data[:, i] - avgs[i]) / (maximums[i] - minimums[i])
    
        # 覆盖上面的训练集
        training_data = data[:offset]
        # 剩下的20%为测试集
        test_data = data[offset:]
        return training_data, test_data
    
  3. 模型设计
    模型设计是深度学习模型关键要素之一,也称为网络结构设计,相当于模型的假设空间,即实现模型“前向计算”(从输入到输出)的过程。

    类成员变量有参数w和b。通过写一个forward函数(代表“前向计算”)完成上述从特征和参数到输出预测值的计算过程,代码如下所示。

    class Network(object):
        def __init__(self, num_of_weights):
            # 随即产生w的初始值
            # seed(0)表示设置了随机种子,保证程序每次运行结果的一致性
            np.random.seed(0)
            # self.w的结构为num_of_weights行,1列
            self.w = np.random.randn(num_of_weights, 1)
            # b初始化为0
            self.b = 0.
    
        def forward(self, x):
            # dot()功能:向量点积和矩阵乘法
            # 根据下面x的取值可以确定x和z的结构
            z = np.dot(x, self.w) + self.b
            return z
    
  4. 训练配置
    模型设计完成后,需要通过训练配置寻找模型的最优值,即通过损失函数来衡量模型的好坏。训练配置也是深度学习模型关键要素之一。
    在Network类下面添加损失函数,代码如下:

        def loss(self, z, y):
            # 根据下面y的取值可以确定y的结构
            error = z - y
            # num_samples为总行数404
            num_samples = error.shape[0]
            # cost为均方误差,用来评价模型的好坏
            cost = error * error
            # 计算损失时需要把每个样本的损失都考虑到
            # 对单个样本的损失函数进行求和,并除以样本总数
            cost = np.sum(cost) / num_samples
            return cost
    
  5. 训练过程
    训练过程是深度学习模型的关键要素之一,其目标是让定义的损失函数Loss尽可能的小,也就是说找到一个参数解w和b使得损失函数取得极小值。
    使用梯度下降法,并用numpy进行梯度计算,在Network类下面添加gradient函数,代码如下:

        def gradient(self, x, y):
            # 调用forward函数,得到z
            z = self.forward(x)
            # 计算w梯度,得到一个13维向量,每个分量分别代表该维度的梯度
            gradient_w = (z - y) * x
            # 均值函数mean:求均值
            # axis 不设置值,对 m*n 个数求均值,返回一个实数
            # axis = 0:压缩行,对各列求均值,返回 1* n 矩阵
            # axis =1 :压缩列,对各行求均值,返回 m *1 矩阵
            gradient_w = np.mean(gradient_w, axis=0)
            # 增加维度,变成 n * 1 的矩阵
            gradient_w = gradient_w[:, np.newaxis]
            # 计算b的梯度
            gradient_b = (z - y)
            # b为一个数值,不需要再增加维度
            gradient_b = np.mean(gradient_b)
            return gradient_w, gradient_b
    

    确定损失函数更小的点,封装在train和update函数中,并在Network中添加,代码如下:

    # 确定损失函数更小的点
        # 更新梯度
        def update(self, gradient_w, gradient_b, eta=0.01):
            # 更新参数
            # 相减:参数需要向梯度的反方向移动。
            # eta:控制每次参数值沿着梯度反方向变动的大小,即每次移动的步长,又称为学习率。
            self.w = self.w - eta * gradient_w
            self.b = self.b - eta * gradient_b
    
        # 迭代100次,每次移动0.01
        def train(self, x, y, iterations=100, eta=0.01):
            losses = []
            for i in range(iterations):
                z = self.forward(x)
                L = self.loss(z, y)
                gradient_w, gradient_b = self.gradient(x, y)
                self.update(gradient_w, gradient_b, eta)
                losses.append(L)
                # 循环输出i末尾为9,间隔为10的数据
                if (i + 1) % 10 == 0:
                    print('iter {}, loss{}'.format(i, L))
            return losses
    

    开始训练以及作图,代码如下:

    # 获取数据
    training_data, test_data = load_data()
    # 取训练集全部行的前13列
    x = training_data[:, :-1]
    # 取训练集全部行的最后一列
    y = training_data[:, -1:]
    # 创建网络
    net = Network(13)
    num_iterations = 1000
    # 启动训练,迭代次数为1000,步长为0.01
    losses = net.train(x, y, iterations=num_iterations, eta=0.01)
    
    # 画出损失函数的变化趋势
    plot_x = np.arange(num_iterations)
    plot_y = np.array(losses)
    plt.plot(plot_x, plot_y)
    plt.show()
    
    

    输出结果:
    在这里插入图片描述

  6. 使用随机梯度下降法提高效率
    在上述程序中,每次损失函数和梯度计算都是基于数据集中的全量数据。但在实际问题中,数据集往往非常大,如果每次都使用全量数据进行计算,效率非常低。
    一个合理的解决方案是每次从总的数据集中随机抽取出小部分数据来代表整体,基于这部分数据计算梯度和损失来更新参数,这种方法被称作随机梯度下降法(Stochastic Gradient Descent,SGD),核心概念如下:

    min-batch:每次迭代时抽取出来的一批数据被称为一个min-batch。
    batch_size:一个mini-batch所包含的样本数目称为batch_size。
    epoch:当程序迭代的时候,按mini-batch逐渐抽取出样本,当把整个数据集都遍历到了的时候,则完成了一轮的训练,也叫一个epoch。启动训练时,可以将训练的轮数num_epochs和batch_size作为参数传入。

    需要修改数据处理和训练过程的代码
    代码修改:

    	# 计算梯度的另一种方法,可以不修改
        def gradient(self, x, y):
            z = self.forward(x)
            # 取数据的行数
            N = x.shape[0]
            # 计算w的梯度,总数相加再除以N
            gradient_w = 1. / N * np.sum((z-y) * x, axis=0)
            # 增加维度
            gradient_w = gradient_w[:, np.newaxis]
            # 计算b的梯度,同上
            gradient_b = 1. / N * np.sum(z-y)
            return gradient_w, gradient_b
    

    训练数据导入后,越接近模型训练结束,最后几个批次数据对模型参数的影响越大。为了避免模型记忆影响训练效果,需要进行样本乱序操作

    # num_epoches为训练的轮数,eta为步长
        def train(self, training_data, num_epoches, batch_size=10, eta=0.01):
            n = len(training_data)
            losses = []
            for epoch_id in range(num_epoches):
                # 打乱样本顺序
                np.random.shuffle(training_data)
                # 将train_data分成多个mini_batch
                # 循环取值,每次取出batch_size条数据
                mini_batches = [training_data[k:k+batch_size] for k in range(0, n, batch_size)]
                for iter_id, mini_batche in enumerate(mini_batches):
                    # 取mini_batch的前13列
                    x = mini_batche[:, :-1]
                    # 取mini_batch的最后1列
                    y = mini_batche[:, -1:]
                    # 前向计算
                    a = self.forward(x)
                    # 计算损失
                    loss = self.loss(a, y)
                    # 计算梯度
                    gradient_w, gradient_b = self.gradient(x, y)
                    # 更新参数
                    self.update(gradient_w, gradient_b, eta)
                    losses.append(loss)
                    print('Epoch {:3d} / iter {:3d}, loss = {:.4f}'.format(epoch_id, iter_id, loss))
            return losses
    

    开始训练以及作图,代码如下:

    # 获取数据
    training_data, test_data = load_data()
    # 创建网络
    net = Network(13)
    # 启动训练,训练50轮,每轮样本数目为100,步长为0.1
    losses = net.train(training_data, num_epoches=50, batch_size=100, eta=0.1)
    
    # 画出损失函数的变化趋势
    plot_x = np.arange(len(losses))
    plot_y = np.array(losses)
    plt.plot(plot_x, plot_y)
    plt.show()
    
    

    输出结果:
    在这里插入图片描述

  7. 总结
    在两层循环的内部中经典的四步训练流程:前向计算->计算损失->计算梯度->更新参数

参考:

【1】https://www.paddlepaddle.org.cn/tutorials/projectdetail/342081
【2】https://blog.csdn.net/qq_34732729/article/details/104015433
【3】https://blog.csdn.net/program_developer/article/details/78637711

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深度学习——入门经典案例《波士顿房价预测》深度解析 的相关文章

  • Xcode 使用 Instruments 无法找到代码中耗时挂起操作的解决

    问题现象 Instruments 是一套非常有用的代码分析和调试利器 我们经常用它来查找 App 中的性能瓶颈 不过 有时 Instruments 却无法捕获到系统明显挂起或长耗时的方法 这是怎么回事呢 如上图所示 App 运行中系统 Se
  • 用 DISM 命令备份与还原 Windows 系统

    一 初始备份 xff08 例如 xff1a 把 C 分区的系统备份到 D 分区的 Win8BF 文件夹中 xff0c 备份文件名为 Win8Pro wim xff09 xff1a Dism Capture Image ImageFile D
  • Unresolved reference: viewModels,viewModels()方法找不到

    遇到的问题 最近在学习LiveData和ViewModel xff0c 跟着官网敲 xff0c 碰到了以下情况 span class token keyword private span span class token keyword v
  • 天干地支计算

    年的干支 方法一 xff1a 首先要能记住十大天干和十二地支 xff0c 十天干 xff1a 甲 乙 丙 丁 戊 己 庚 辛 壬 癸 xff1b 十二地支 xff1a 子 丑 寅 卯 辰 巳 午 未 申 酉 戌 亥 xff1b 天干地支纪年
  • 程序员们,AI来了,机会来了,危机也来了

    程序员们 xff0c AI来了 xff0c 机会来了 xff0c 危机也来了 1 人工智能真的来了 纵观古今 xff0c 很少有计算机技术能有较长的发展寿命 xff0c 大部分昙花一现 xff0c 比如 xff1a 昔日的DOS windo
  • 统信UOS 20 1050 记录一次openssl升级失败的排查过程

    目录 不能找到openssl最新版本的原因 fedora有相关module的介绍 一些yum module 常用的命令 xff1a 查看yum module 都有哪些 启用禁用module 总结 xff1a 后记 xff1a 通过yum l
  • iOS之富文本

    之前做项目时遇到一个问题 xff1a 使用UITextView显示一段电影的简介 xff0c 由于字数比较多 xff0c 所以字体设置的很小 xff0c 行间距和段间距也很小 xff0c 一大段文字挤在一起看起来很别扭 xff0c 想要把行
  • JetBrains IntelliJ IDEA 2022.2 使用 Java 17 运行时

    JetBrains 发布 了 IntelliJ IDEA 2022 2 xff0c 支持 Java 17 和最新的语言和框架 xff0c 如 Scala Kotlin Spring 6 和 Spring Boot 3 这个新版本使用了 Je
  • Linux生产者消费者模型实现

    转载请注明出处 xff1a https blog csdn net mymottoissh article details 84181224 任何语言提及到多线程同步都离不开生产者 消费者模型 这也是针对许多现实问题建模用到的基础模型 这一
  • 使用CMD启动JAR后,出现定时器不执行问题

    SpringBoot项目中 使用了 64 Scheduled注解开启一个定时任务 在windows系统启动时 开始输出正常 当执行到输出控制台日志时 有时候会直接卡住线程不执行了 查了一圈发现是CMD的快速编辑引起的线程阻塞 解决办法 1
  • Flink开发中遇到的问题及解法

    1 当Source是Kafka的时候 xff0c 如何设置Source Operator的并发度 xff1f 如果没有指定 xff0c Source Operator的个数与集群中的TaskManager的个数相等 如果手动设置 xff0c
  • vue初学者代码格式报错

    报错内容 xff1a Do not use built in or reserved HTML elements as component id header
  • Ubuntu 设置su密码

    在使用su命令获取超级权限的时候提示输入密码 xff0c 在安装ubuntu的时候只设置了用户密码 xff0c 没记得有其他密码 这里需要给root用户重新设置密码 xff1a sudo passwd 然后输入密码即可
  • Spark MLlib学习(二)——分类和回归

    MLlib支持多种分类方法 xff0c 如二分类 多分类和回归分析等 问题类型 支持的方法 二分类 线性SVM 逻辑回归 xff0c 决策树 xff0c 随机森林 xff0c GBDT xff0c 朴素贝叶斯 多分类 决策树 xff0c 随
  • 关于onNewIntent你应该知道的

    一 API描述如下 大概意思是当Activity被设以singleTop模式启动 xff0c 当需要再次响应此Activity启动需求时 xff0c 会复用栈顶的已有Activity xff0c 还会调用onNewIntent方法 并且 x
  • 程序猿的情话

    世界上最遥远的距离 xff0c 是我在if里你在else里 xff0c 似乎一直相伴又永远分离 xff1b 世界上最痴心的等待 xff0c 是我当case你是switch xff0c 或许永远都选不上自己 xff1b 世界上最真情的相依 x
  • SpringBoot JPA实践之EntityManage查询返回自定义DTO

    在很多时候我更喜欢随意组合查询出来返回一个DTO对象的实现 xff0c JPA提供的多数查询均以返回Entity居多 xff0c 它提供的EntityManager对象可以实现将SQL语句查询的结果转换为自定义DTO对象 xff08 这与
  • 经典编程书籍(C++, 网络, Windows, Linux)【转载】

    书单中列举的都是相关领域的经典书籍 xff0c 必读之作 此书单的编辑参考了很多网站 xff0c 包括一些名家的推荐 xff0c 例如侯捷 xff0c 孟岩 xff0c 荣耀 xff0c 潘爱民等等 xff0c 在此也向这些前辈表示感谢 1
  • SpringBoot微服务框架概述

    SpringBoot微服务框架 2 Spring Boot 微服务框架的特点3 Spring Boot 应用场景4 SpringBoot的第一个应用5 Springboot引导类的main方法有什么作用 xff1f 6 SpringBoot
  • 使用Spring的注解方式实现AOP

    Spring对AOP的实现提供了很好的支持 下面我们就使用Spring的注解来完成AOP做一个例子 首先 xff0c 为了使用Spring的AOP注解功能 xff0c 必须导入如下几个包 aspectjrt jar aspectjweave

随机推荐

  • 如何正确有效的学习一门计算机语言?

    在这个互联网高速发展的社会 xff0c 越来越多的人喜欢上了IT行业 xff0c 认为计算机行业是一个高科技的 高薪的行业 的确如此 xff0c 但是系统的学习一门计算机语言 xff0c 并且把它用运用到真正的开发中去还真不是一件简单的事情
  • (二)为AI和机器学习创建Docker容器

    目录 介绍 基本镜像 创建Dockerfile 构建镜像 运行容器 总结 下载源文件 154 4 KB 介绍 Docker 等容器技术显着简化了软件的依赖管理和可移植性 在本系列文章中 xff0c 我们探讨了 Docker 在机器学习 ML
  • 自定义EF Core迁移历史记录表

    目录 背景 更改表名称和架构 更改列名称 添加具有默认值的列 添加必填列 关于代码示例 引用 下载源代码 13 9 KB 背景 实体框架核心通过在名为 EFMigrationsHistory 和架构 dbo 的表中添加日志来跟踪应用的迁移
  • 使用EF Core 6执行原始SQL查询

    目录 背景 现有选项 ExecuteSqlRaw 插入 更新 删除 FromSqlRaw FromSqlInterpolated 自定义数据库上下文扩展方法 ExecuteScalar ExecuteNonQuery FromSqlQuer
  • 仓库更新了,git pull拉取远端失败

    仓库更新了 span class token punctuation span git pull拉取远端失败 span class token operator span error span class token operator sp
  • xPath 用法总结整理

    最近在研究kafka xff0c 看了一堆理论的东西 xff0c 想动手实践一些东西 xff0c 奈何手上的数据比较少 xff0c 突发奇想就打算写个爬虫去抓一些数据来玩 xff0c 顺便把深入一下爬虫技术 之前写过一些小爬虫 xff0c
  • vi编辑器

    目录 简介 基本操作 1 移动光标 2 定位 3 删除 4 复制 5 查找
  • 使用libevent搭建简单http服务器

    64 使用libevent搭建简单http服务器 一 libevent 的下载 可通过官网直接进行下载libevent库 xff1b 例子使用的是V2 1 1版本 xff0c 下载完成后 xff0c 解压 xff1b 可以再解压目录下获取
  • C++动态链接库中的全局变量面试题

    其实主要问题是三个模块 xff1a 模块 a 静态库 a 模块 b 二进制 b 静态引用a 动态加载c 模块 c 动态链接库c 静态引用a 关键在于静态库a里有一个静态全局变量 xff0c 没错就是我们的日志模块 原先的这个静态的模块中的静
  • Linux 桌面修改文件mime类型图标

    在多数的Linux发行版中 xff0c 默认的桌面的文件类型图标着实不好看 xff0c 比如我常用的Linux之一Debian xff0c 默认文件类型图标就很不好看 如果我们自定义了一种mime类型的话肯定也是没有图标的啦 xff0c 下
  • 比 MyBatis 快了 100 倍

    比 MyBatis 效率快 100 倍的条件检索引擎 xff0c 天生支持联表 xff0c 使一行代码实现复杂列表检索成为可能 xff01 2开源协议 使用Apache 2 0开源协议 3界面展示 你的产品给你画了以上一张图 xff0c 还
  • 【GIT】GIT基础教程(新手必看)

    准备工作 1 首先要下载git xff0c git官网下载比较缓慢 xff0c 这里提供一个淘宝镜像的网站 https npm taobao org mirrors git for windows 里边有各种版本的git xff0c 选择与
  • Python常见内置类属性介绍

    文章目录 64 TOC 文章目录 什么是内置类属性一 dict 的用法二 name 的用法三 file 的用法 什么是内置类属性 当python创建一个类之后 xff0c 系统就自带了一些属性 xff0c 叫内置类属性 这些属性名用双下划线
  • win32应用程序和win32控制台应用程序

    win32应用程序是有窗体的 xff08 当然也可以没有 xff09 xff0c 有Windows消息循环机制的 而win32控制台应用程序只是在控制台下运行的程序 xff0c 类似以前dos的程序 Win32 Application和Wi
  • springBoot 启动指定配置文件环境多种方案

    springBoot 启动指定配置文件环境理论上是有多种方案的 xff0c 一般都是结合我们的实际业务选择不同的方案 xff0c 比如 xff0c 有pom xml文件指定 maven命令行指定 配置文件指定 启动jar包时指定等方案 xf
  • tigervnc黑屏及mate-session缺失

    1 项目信息 host os xff1a Kylin Server V10 arm64 2022 04 29 2 问题描述及原因分析 通过一下命令安装vnc server yum install tigervnc server 然后通过vn
  • (Java)集合工具类:Collections

    文章目录 一 Collections 简介二 Collections 操作实例1 实例操作一 xff1a 返回不可变的集合2 实例操作二 xff1a 为集合增加内容3 实例操作三 xff1a 反转集合中的内容4 实例操作四 xff1a 检索
  • Seata快速开始

    Seata分TC TM和RM三个角色 xff0c TC xff08 Server端 xff09 为单独服务端部署 xff0c TM和RM xff08 Client端 xff09 由业务系统集成 Seata Server 部署 步骤一 xff
  • 点击Anaconda中的Jupyter Notebook无法打开浏览器

    解决方法一 xff1a 通过修改配置文件来指定浏览器打开notebook 步骤 xff1a 打开anaconda promote 输入 xff1a jupyter notebook generate config 输出结果 xff1a Wr
  • 深度学习——入门经典案例《波士顿房价预测》深度解析

    一 深度学习 机器学习算法理论在上个世纪90年代发展成熟 xff0c 在许多领域都取得了成功应用 但平静的日子只延续到2010年左右 xff0c 随着大数据的涌现和计算机算力提升 xff0c 深度学习模型异军突起 xff0c 极大改变了机器