Tensorflow回归入门实践-预测70年代末到80年代初汽车燃油效率的模型(详解,提供数据集)

本文主要是介绍Tensorflow回归入门实践-预测70年代末到80年代初汽车燃油效率的模型(详解,提供数据集),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章较长,可以跳转查看需要的部分

  • 回归的目的
  • 数据集(提供网盘下载)
    • 网盘下载(如果无法直接下载数据集)
  • 基本实现结构的分析(数据部分)
    • 首先引入需要的模块or包
    • 获取数据集(本地数据集读取)
    • 设置数据标签
      • 补充data文件类型:
    • 使用panda读取数据集
    • 对数据进行处理(一)
    • 对数据进行处理(二)
    • 对数据进行处理(三)
    • 数据归一化
  • 模型分析
    • 模型构建
    • 模型检测
    • 数据拟合
  • 训练结果数据展示(建议使用jupyter notebook)
    • 模型日志的查看
    • 模型训练的日志信息-可视化
      • 创建绘图函数
      • 可视化展示(发现训练多了反而出问题了——过拟合)
  • 模型改进
  • 模型评估
  • 使用完整的测试数据预测(最后阶段可视化)
    • 预测MPG的数据可视化
    • 误差分布可视化
  • 总结

                         QQ:3020889729                                                                                 小蔡

这是一个学习例程的学习分享,希望对tensorflow的学习和理解有所帮助,当然还有API-keras本身的认识提升。
(本博客提供数据集下载(备份),是因为原官方数据集在下载时,出现链接超时的失败问题。)
(建议使用jupyter notebook)
(文章较长,还望根据需要合适的阅读——有效利用学习时间。)

回归的目的

与其说什么是回归来促进理解,我觉得了解回归的目的是什么会更有效。
回归是为了,预测出如价格或概率以及某种这样连续值/信息的输出。
比如,我给一段连续时间的食品销售量,然后在相同的条件下去预估接下来一段时间或下一次可能的结果。(这和我们上学时,接触的数学回归问题,得到一个回归方程展示其在具体问题中的实际意义是一样的。)
与分类相比,它的目的是为了预测下一段时间/空间最可能出现的结果,不同于分类需要具体的图像或者感知才进行预测是什么。

数据集(提供网盘下载)

本次使用的数据集是Auto MPG数据集——我们将利用它来构建一个用于预测70年代末到80年代初汽车燃油效率的模型。

该数据集包含信息:气缸数,排量,马力以及重量

网盘下载(如果无法直接下载数据集)

数据集下载:https://pan.baidu.com/s/13fCzCHk3Myhdv0X70QL0Fw
提取码:bnoz

基本实现结构的分析(数据部分)

首先引入需要的模块or包

  • import pathlib # 引入文件路径操作的模块
  • import pandas as pd # 引入panda科学数据处理包
  • import seaborn as sns # 引入seaborn——绘图包,在pycharm中使用,需要调用pyplot的show()
  • import matplotlib.pyplot as plt # 标准绘图包
  • import tensorflow as tf # 引入tensorflow包
  • from tensorflow import keras # 引用tf包下的keras——这就是我们将用使用的高级API
  • from tensorflow.keras import layers # 引出layers模块,这是网络层相关的模块

关于下载包/模块,需要说明几点(这里默认下载好了tensorflow):

  1. pathlib无需下载——内置
  2. seaborn需要下载,最好用pip,conda可能会有问题
  3. keras可能在一开始下载tensorflow后没有,那你需要单独下载keras——如果是2.0.0及以上的tensroflow只需要安装比较新的keras即可(也就是直接pip)。

代码:

import pathlib
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers

获取数据集(本地数据集读取)

无论是否是去Auto MPG下载的数据集,都还是调用以下方法加载数据集本地路径:

keras.utils.get_file("auto-mpg.data", "http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data")

如果是通过网盘下载的数据集,我们都需要将数据集放在C盘的user文件夹下的.keras文件夹里的datasets下:即:C->user(也就是用户根目录)->.keras->datasets
如果没有文件就user目录下,创建对应的文件,然后存放数据集。

代码:

dataset_path = keras.utils.get_file("auto-mpg.data", "http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data")
dataset_path  # 可查看数据——jupyter notebook可直接显示,pycharm需要print

效果:(我已经下载放在指定目录,所以没有下载步骤的显示)
在这里插入图片描述

设置数据标签

由于读取的数据是是一个data文件,本身就类似于表格,所以我们需要为其读取前,设置好对应的列名-标签。

column_names = ['MPG','Cylinders','Displacement','Horsepower','Weight','Acceleration', 'Model Year', 'Origin']

数据标签含义:

  • MPG:每加仑燃料所行英里数
  • Cylinders:气缸数
  • Displacement:排量
  • Horsepower:马力
  • Weight:重量
  • Acceleration:加速能力
  • Model Year:车型年份——即生产(研发)年份
  • Origin:产源地

代码:

column_names = ['MPG','Cylinders','Displacement','Horsepower','Weight','Acceleration', 'Model Year', 'Origin']

补充data文件类型:

DataFrame是Pandas中的一个表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame即有行索引也有列索引,可以被看做是由Series组成的字典。

使用panda读取数据集

需要说明以下主要参数:依次为路径,索引名,空(无效)值设置,指定注释行,分隔符,是否考虑为False的数据

raw_dataset = pd.read_csv(dataset_path, names=column_names,na_values = "?", comment='\t',sep=" ", skipinitialspace=True)

参数含义对应展示:

  1. dataset_path——读取路径
  2. names——数据读取后的列索引名
  3. na_values——空(无效)值设置,这里设置为?
  4. comment——指定‘\t’对应的行为注释行,不读取
  5. sep——数据分隔符
  6. skipinitialspace——是否考虑为False的数据,即数据中存在False的bool值是被允许的

代码:

raw_dataset = pd.read_csv(dataset_path, names=column_names,na_values = "?", comment='\t',sep=" ", skipinitialspace=True)dataset = raw_dataset.copy()  # 复制读取的数据,避免修改元数据
dataset.tail()  # 显示表格数据——jupyter自显,pycharm需要print

效果:
在这里插入图片描述

对数据进行处理(一)

主要是删除无效值和数据分类操作

  1. 数据清洗——首先是无效数据查看:isna()会返回为包含无效值的表单,再追加一个sum()实现计算无效值的和;其次,对无效数据进行处理:dropna()清除无效数据后返回一个新数据表单。
  2. 将需要的产源地分类序号从表中提取出来,使用pop(‘Origin’)提取Origin列的数据
  3. 将Origin进行one-hot转换——即Origin不同的值仅对应一个数据有效:
  4. dataset['USA'] = (origin == 1)*1.0
  5. dataset['Europe'] = (origin == 2)*1.0
  6. dataset['Japan'] = (origin == 3)*1.0——如此,仅当对应的标号时,某一列中的数据才为1,满足one-hot定义:[0,0,1,0,0……1,0],只有有效数据为1,其余为零。

代码:

dataset.isna().sum()  # 显示无效数据分布情况

效果:
在这里插入图片描述

dataset = dataset.dropna()  # 移除无效数据

效果:
在这里插入图片描述

origin = dataset.pop('Origin')  # 获取分类序号——以供one-hot转换需要

效果:
在这里插入图片描述

dataset['USA'] = (origin == 1)*1.0  
# one-hot转换:只有当列数据中值为1时,才设为1,否则为0,也就相当于一整列数据按 (origin == 1)条件转换为1 or 0dataset['Europe'] = (origin == 2)*1.0
dataset['Japan'] = (origin == 3)*1.0
dataset.tail()  # 显示表格数据

效果:
在这里插入图片描述

对数据进行处理(二)

主要是拆分数据集和获取数据状况分析信息

  1. 采用sample(frac=0.8,random_state=0)——随机拆分80%的panda的DataFrame数据作为训练集
  2. 采用drop(train_dataset.index)——移除已经取出的数据下标包含的数据并返回。
  3. describe()用于观察一系列数据的范围,大小、波动趋势等等。(会存到train_stats)
  4. 补充说明,描述信息需要pop(‘MPG’)——因为这是我们需要单独处理的数据。

代码:

train_dataset = dataset.sample(frac=0.8,random_state=0)  # 拆分获得训练数据
test_dataset = dataset.drop(train_dataset.index)  # 拆分获得测试数据

效果:
在这里插入图片描述
在这里插入图片描述

train_stats = train_dataset.describe()  # 获取数据的一系列描述信息
train_stats.pop("MPG")  # 移除MPG的数据列
train_stats = train_stats.transpose()  # 行列转换——也就是相当于翻转
train_stats  # 显示描述信息——jupyter自显

效果:
在这里插入图片描述

对数据进行处理(三)

主要是分离训练数据的标签——从获得的数据中。

  1. 同样采用pop(‘MPG’)——获取指定列的数据

代码:

train_labels = train_dataset.pop('MPG')   # 将移除的MPG列数据返回,赋值给train_labels 
test_labels = test_dataset.pop('MPG')
train_labels   # 显示数据
test_labels 

效果:
在这里插入图片描述
在这里插入图片描述

数据归一化

在这次的数据中,虽然说只是一些简单数据的分析,但是数据归一化,特征归一化还是很有必要的。这样有助于数据收敛,得到更好的训练结果。
采用的计算方式如下:x为需要归一化的数据,train_stats为当前表格的描述信息——通过以下运算就实现了归一化。(0 or 1)

(x - train_stats['mean']) / train_stats['std']

这样获得的归一化数据,应该是被保留下来用与后边的其它运算。

代码:
(采用函数,方便多次调用,避免公式重复导致可读性,降低人为失误)

def norm(x):return (x - train_stats['mean']) / train_stats['std']
normed_train_data = norm(train_dataset)  # 获取训练数据中的归一化数据
normed_test_data = norm(test_dataset)  # 获取测试归一化数据

效果:
在这里插入图片描述
在这里插入图片描述

模型分析

模型构建

本模型采用线性模型——包含两个紧密相连的隐藏层,以及返回单个、连续值得输出层。
为了代码结构,采用函数式编程:执行模型——网络层结构创建,以及模型编译。

# 第一层Dense的input_shape为输入层大小,前边的64为该全连接层的输出层(隐藏层)——只有最后的全连接层 layers.Dense(1)输出才是输出层,否则为隐藏层。
# activation为激活函数——这里是线性激活
def build_model():model = keras.Sequential([layers.Dense(64, activation='relu', input_shape=[len(train_dataset.keys())]),layers.Dense(64, activation='relu'),layers.Dense(1)])optimizer = tf.keras.optimizers.RMSprop(0.001)model.compile(loss='mse',optimizer=optimizer,metrics=['mae', 'mse'])return model
model = build_model()  # 创建一个模型
model.summary()  # 展示模型结构

效果:
在这里插入图片描述

模型检测

采用上边创建好的模型进行预测——查看效果。

example_batch = normed_train_data[:10]  # 获取十个数据来预测
example_result = model.predict(example_batch)
example_result

效果:(看起来似乎它已经可以用来直接使用了,但其实这还不够,我们一定记得要进行拟合数据才算是一个完整的学习模型的构建完全。)
在这里插入图片描述

数据拟合

在这里添加一个输出点的函数——目的是显示训练的进程(提示:本次训练拟合周期(次数)为1000,你也可以进行更多的尝试)

# 通过为每个完成的时期打印一个点来显示训练进度
class PrintDot(keras.callbacks.Callback):def on_epoch_end(self, epoch, logs):if epoch % 100 == 0: print('')print('.', end='')
EPOCHS = 1000  # 拟合次数# 返回的history为一个对象,内包含loss信息等
history = model.fit(normed_train_data, train_labels,epochs=EPOCHS, validation_split = 0.2, verbose=0,callbacks=[PrintDot()])

拟合fit函数的参数依次为:

  1. 训练所需的归一化数据,训练数据对应的标签;
  2. 拟合次数
  3. validation_split用于在没有提供验正集的时候,按一定比例从训练集中取出一部分作为验证集
  4. 日志显示配置:verbose = 0 为不在标准输出流输出日志信息
    verbose = 1 为输出进度条记录
    verbose = 2 为每个epoch输出一行记录
    注意: 默认为 1
  5. callbacks——简单的说就是提供训练中的操作

效果:
在这里插入图片描述

训练结果数据展示(建议使用jupyter notebook)

模型日志的查看

hist = pd.DataFrame(history.history)  # 返回一个DataFrame对象,包含history的history数据
hist['epoch'] = history.epoch  # 末尾添加一列数据包含epoch信息
hist.tail()  # 展示表单数据

效果:
在这里插入图片描述
在这里插入图片描述

模型训练的日志信息-可视化

创建绘图函数

def plot_history(history):hist = pd.DataFrame(history.history)hist['epoch'] = history.epochplt.figure()  # 创建新窗口plt.xlabel('Epoch')  # x轴标签(名字)plt.ylabel('Mean Abs Error [MPG]')  # y轴标签(名字)plt.plot(hist['epoch'], hist['mae'],label='Train Error')  # 绘图,label为图例plt.plot(hist['epoch'], hist['val_mae'],label = 'Val Error')  # 绘图,label为图例plt.ylim([0,5])  # y轴长度限制plt.legend()  # 展示图例plt.figure()plt.xlabel('Epoch')plt.ylabel('Mean Square Error [$MPG^2$]')plt.plot(hist['epoch'], hist['mse'],label='Train Error')plt.plot(hist['epoch'], hist['val_mse'],label = 'Val Error')plt.ylim([0,20])plt.legend()plt.show()  # 必须要有show才能显示绘图

可视化展示(发现训练多了反而出问题了——过拟合)

有一个问题:也许你的图形不一样,这可能是数据训练和机器相关。
在这里插入图片描述

模型改进

以下模型改进——在jupyter notebook中可以直接进行,而使用pycharm的朋友需要在原来的位置进行替换(early_stop添加在原fit前)

model = build_model()  # 重新定义模型# patience 值用来检查改进 epochs 的数量
# 定义callbacks的操作设置,这里采用了每10次fit,进行一次判断是否停下,判断依据是当val_loss不改变甚至降低。
early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)  history = model.fit(normed_train_data, train_labels, epochs=EPOCHS,validation_split = 0.2, verbose=0, callbacks=[early_stop, PrintDot()])plot_history(history)

效果:看得出,模型有效准确值稳定在了一定范围后,训练就停止了。
在这里插入图片描述

模型评估

loss, mae, mse = model.evaluate(normed_test_data, test_labels, verbose=2)  # 返回第一个数据loss为损失值
print("Testing set Mean Abs Error: {:5.2f} MPG".format(mae))  # mae为我们构建网络归回预测的值——即预测的MPG

打印结果:说明MPG稳定在2.00左右
在这里插入图片描述

使用完整的测试数据预测(最后阶段可视化)

预测MPG的数据可视化

test_predictions = model.predict(normed_test_data).flatten()  
# 预测信息会被flatten()平铺展开后以一维数据返回plt.scatter(test_labels, test_predictions)  # 绘制散点图
plt.xlabel('True Values [MPG]')
plt.ylabel('Predictions [MPG]')
plt.axis('equal')
plt.axis('square')
plt.xlim([0,plt.xlim()[1]])
plt.ylim([0,plt.ylim()[1]])
_ = plt.plot([-100, 100], [-100, 100])  # 画一条y = x的直线,方便分析

效果:(MPG数据基本集中于该直线)
在这里插入图片描述

误差分布可视化

error = test_predictions - test_labels  # test_labels 是原始的MPG值序列,所以相减得到误差。
plt.hist(error, bins = 25)  # 画矩形图——bins表示每次绘图的最大矩形数目
plt.xlabel("Prediction Error [MPG]")
_ = plt.ylabel("Count")

效果误差主要分布在-2~2之间,0最多。说明训练模型较为合适。
在这里插入图片描述

总结

  1. 常见的回归指标是平均绝对误差(MAE)。
  2. 均方误差(MSE)是用于回归问题的常见损失函数(分类问题中使用不同的损失函数)。
  3. 当数字输入数据特征的值存在不同范围时,每个特征应独立缩放到相同范围。(归一化,一般采用one-hot编码形式)
  4. 早期停止是一种防止过度拟合的有效技术。

这篇入门讲解到这里就全部结束了。也许我的文章写得不是很好,还有点长长的——希望对阅读到这里的你有所帮助。

如果对函数参数,或者函数方法有疑惑,需要解答的,可以评论,我尽量回答。如果有需要,我后边可以补写一篇关于这部分参数和函数的讲解。(因为这篇文章实在有点太长了。)

这篇关于Tensorflow回归入门实践-预测70年代末到80年代初汽车燃油效率的模型(详解,提供数据集)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/369959

相关文章

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

mac中资源库在哪? macOS资源库文件夹详解

《mac中资源库在哪?macOS资源库文件夹详解》经常使用Mac电脑的用户会发现,找不到Mac电脑的资源库,我们怎么打开资源库并使用呢?下面我们就来看看macOS资源库文件夹详解... 在 MACOS 系统中,「资源库」文件夹是用来存放操作系统和 App 设置的核心位置。虽然平时我们很少直接跟它打交道,但了

关于Maven中pom.xml文件配置详解

《关于Maven中pom.xml文件配置详解》pom.xml是Maven项目的核心配置文件,它描述了项目的结构、依赖关系、构建配置等信息,通过合理配置pom.xml,可以提高项目的可维护性和构建效率... 目录1. POM文件的基本结构1.1 项目基本信息2. 项目属性2.1 引用属性3. 项目依赖4. 构

Rust 数据类型详解

《Rust数据类型详解》本文介绍了Rust编程语言中的标量类型和复合类型,标量类型包括整数、浮点数、布尔和字符,而复合类型则包括元组和数组,标量类型用于表示单个值,具有不同的表示和范围,本文介绍的非... 目录一、标量类型(Scalar Types)1. 整数类型(Integer Types)1.1 整数字

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

PyTorch使用教程之Tensor包详解

《PyTorch使用教程之Tensor包详解》这篇文章介绍了PyTorch中的张量(Tensor)数据结构,包括张量的数据类型、初始化、常用操作、属性等,张量是PyTorch框架中的核心数据结构,支持... 目录1、张量Tensor2、数据类型3、初始化(构造张量)4、常用操作5、常用属性5.1 存储(st