【实验课程】汽车里程数回归预测实验

实验介绍

简介

本实验主要内容是进行汽车油耗里程数的预测,用到的框架主要包括:MindSpore0.5.0,主要用于深度学习算法的构建,本实验以开源的auto-mpg数据集为基础,基于MindSpore0.5.0深度学习库应用全连接神经网络进行汽车里程数预测。

实验目的

本实验是完成了一项回归任务。所以,本实验的重点在于区别分类任务与回归任务中网络结构的不同。

实验环境要求

推荐在华为云ModelArts实验平台完成实验,也可在本地搭建python3.7和MindSpore0.5.0环境完成实验。

实验总体设计

image.png

导入实验所需模块:该步骤通常都是程序编辑的第一步,将实验代码所需要用到的模块包用import命令进行导入。

导入数据集并预处理:神经网络的训练离不开数据,这里对数据进行导入。对数据集中的字符特征进行one-hot编码。同时,查看数据特征间的关联关系。

模型搭建与训练:利用mindspore.nn的cell模块搭建全连接网络,包含输入层,隐藏层,输出层。同时,配置好网络需要的优化器,损失函数和评价指标。传入数据,并开始训练模型。本实验是做回归任务,所以输出层的输出结果是1维的。

查看模型训练状态:利用MAE和MSE两个评价指标来查看模型在训练过程中的状态。

实验过程

导入实验所需模块

 

#安装相关依赖包
import  os
# os.environ['DEVICE_ID'] = '0'
 
import csv
import time
import numpy as np
import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt
 
import mindspore as ms
import mindspore.dataset as ds
import mindspore.context as context
import mindspore.dataset.transforms.c_transforms as C
import mindspore.dataset.transforms.vision.c_transforms as CV
from mindspore import nn, Tensor
from mindspore.train import Model
from mindspore.nn.metrics import Accuracy, MAE, MSE
from mindspore.dataset.transforms.vision import Inter
from mindspore.train.serialization import load_checkpoint, load_param_into_net
from mindspore.train.callback import ModelCheckpoint, CheckpointConfig, LossMonitor, TimeMonitor
 
context.set_context(mode=context.GRAPH_MODE, device_target='Ascend')

导入数据集并预处理

步骤 1 下载数据集

 

# 加载数据集
with open('auto-mpg.data') as csv_file:
    data = list(csv.reader(csv_file, delimiter=','))
# 打印部分数据
print(data[20:40])

步骤 2 利用pandas模块读取数据

Pandas模块是一个处理表格类数据非常有效的模块。

 

# 使用pandas读取数据
column_names = ['MPG','Cylinders','Displacement','Horsepower','Weight',
                'Acceleration', 'Model Year', 'Origin']
raw_data = pd.read_csv('auto-mpg.data', names=column_names,
                      na_values = "?", comment=\t',
                      sep=" ", skipinitialspace=True)
data = raw_data.copy()

# 查看数据形状
data.shape

步骤 3 数据预处理

对于数据集中的空值,我们要在建模前进行处理。此处空值的数据较少,我们直接进行删除。

 

#清洗空数据
dataset = data.dropna()

 

 

Pandas库提供了简单的数据集统计信息,我们可直接调用函数describe()进行查看。

 

#查看训练数据集的结构
origin = data.pop('Origin')
data_labels = data.pop('MPG')
train_stats = data.describe()
train_stats = train_stats.transpose()
train_stats

 

 

#归一化数据
def norm(x):
    return (x - train_stats['mean']) / train_stats['std']
normed_data = norm(data)

 

# 将MPG放回归一化后的数据中
normed_data['MPG'] = data_labels
#将数据集按照4:1划分成训练集和测试集
train_dataset = normed_data.sample(frac=0.8,random_state=0)
test_dataset = normed_data.drop(train_dataset.index)

模型训练需要区分特征值与目标值,也就是我们常说的X值与Y值,此处MPG为Y值,其余的特征为X值。

 

#将目标值和特征分开
train_labels = train_dataset.pop('MPG')
test_labels = test_dataset.pop('MPG')
X_train, Y_train = np.array(train_dataset), np.array(train_labels)
X_test, Y_test = np.array(test_dataset), np.array(test_labels)

 

#查看数据集尺寸
print('训练数据x尺寸:',X_train.shape)
print('训练数据y尺寸:',Y_train.shape)
print('测试数据x尺寸:',X_test.shape)
print('测试数据y尺寸:',Y_test.shape)

离散特征处理

特征Origin代表着车辆的归属区域信息,此处总共分为三种,欧洲,美国,日本,我们需要对此特征进行one-hot编码。

 

# 对origin属性进行one-hot编码
normed_data['USA'] = (origin == 1)*1.0
normed_data['Europe'] = (origin == 2)*1.0
normed_data['Japan'] = (origin == 3)*1.0

 

#将数据集转换为Tensor格式
ds_xtrain= Tensor(X_train, ms.float32)
ds_ytrain= Tensor(Y_train, ms.int32)
ds_xtest=Tensor(X_test, ms.float32)
ds_ytest=Tensor(Y_test, ms.int32)

步骤 4 可视化特征关系

这里利用seaborn模块中的pairplot方法实现特征相关性的简单可视化操作。相关性是特征工程中考察特征间联系的重要手段。在传统机器学习领域,相关性往往决定了如何进行特征选择。

 

#可视化
#在数据建模前,我们一般会进行简单的数据分析,查看数据特征之间的相关性,数据分布。
sns.pairplot(normed_data[["Cylinders", "Displacement", "Weight"]], 
             diag_kind="kde")

输出结果:

image.png

模型搭建与训练

步骤 1 创建网络

汽车油耗里程数据集准备完成,接下来我们就需要构建训练模型,本实验采用的是全连接神经网络算法,所以我们首先需要建立初始化的神经网络。nn.cell能够用来组成网络模型;模型共包含3个全连接,采用Relu当做激活函数

 

#创建模型,共包含3个全连接,采用Relu当做激活函数
class Regression_car(nn.Cell):
    def __init__(self):
        super(Regression_car, self).__init__()
        self.flatten = nn.Flatten()
        self.relu = nn.ReLU()
        self.fc1 = nn.Dense(6,64, activation='relu')
        self.fc2 = nn.Dense(64,64, activation='relu')
        self.fc3 = nn.Dense(64,1, activation='relu')
        
    def construct(self, x):
        x = self.flatten(x)
        x = self.fc1(x)
        x = self.fc2(x)
        x = self.fc3(x)
        return x

步骤 2 设定参数

指定模型所需的损失函数、评估指标、优化器等参数。回归问题,损失函数采用均方误差mse。

 

#定义网络,损失函数,评估指标  优化器
network = Regression_car()
net_loss = nn.MSELoss()
net_opt = nn.RMSProp(network.trainable_params(), 0.001)

步骤 3 训练模型

将创建好的网络、损失函数、评估指标、优化器等参数装入模型中对模型进行训练。需要逐步打印出mae、mse的值

 

#使用单步训练的方式来使结果中打印出MAE、MSE
with_loss=nn.WithLossCell(network,net_loss) 
train_step = nn.TrainOneStepCell(with_loss, net_opt).set_train()

evalcell=nn.WithEvalCell(network,net_loss)

mae = nn.MAE()
mse = nn.MSE()
val_mae = nn.MAE()
val_mse = nn.MSE()
    
#创建一个空的Dataframe
result =pd.DataFrame(columns=('_epoch','_loss','_mae','_mse','val_loss','val_mae','val_mse'))
print("============== Starting Training ==============")
for epoch in range(1000):
    #print(ds_xtrain.shape)
    loss,val_loss = train_step(ds_xtrain,ds_ytrain),train_step(ds_xtest, ds_ytest)

    _, outputs, label = evalcell(ds_xtrain,ds_ytrain)
    _, val_outputs, val_label = evalcell(ds_xtest,ds_ytest)
    
    #每次循环都更新MAE、MSE等的值。
    mae.clear()
    mae.update(outputs, label)
    mse.clear()
    mse.update(outputs, label)
    val_mae.clear()
    val_mae.update(val_outputs, val_label)
    val_mse.clear()
    val_mse.update(val_outputs, val_label)
    

    Mae = mae.eval()
    Mse = mse.eval()
    Val_Mae = val_mae.eval()
    Val_Mse = val_mse.eval()
    
    nd_loss = loss.asnumpy()
    fl_loss = float(nd_loss)/24.0
    val_nd_loss = val_loss.asnumpy()
    val_fl_loss = float(val_nd_loss)/24.0

    #将计算结果逐行插入result,注意变量要用[]括起来,同时ignore_index=True,否则会报错,ValueError: If using all scalar values, you must pass an index
    result=result.append(pd.DataFrame({'_epoch':[epoch],'_loss':fl_loss,'_mae':Mae,'_mse':Mse,'val_loss':val_fl_loss,
                                       'val_mae':Val_Mae,'val_mse':Val_Mse}),ignore_index=True)

    if epoch%10==0:
        print('epoch:{0},loss:{1},mae:{2},mse:{3},val_loss:{4},val_mae:{5},val_mse:{6}'.format(epoch,fl_loss,Mae,Mse,
                                                                                               val_fl_loss,Val_Mae,Val_Mse))
        print("*" * 110)
result

输出结果:

image.png

1.4.4 查看模型训练状态

绘制模型损失函数图,利用result中的MAE和MSE查看模型训练状态。

 

def plot_history(result):
 
    plt.figure()
    plt.xlabel('Epoch')
    plt.ylabel('Mean Abs Error [MPG]')
    plt.plot(result['_epoch'], result['_mae'],
           label='Train Error')
    plt.ylim([0,20])
    plt.legend()
 
    plt.figure()
    plt.xlabel('Epoch')
    plt.ylabel('Mean Square Error [$MPG^2$]')
    plt.plot(result['_epoch'], result['_mse'],
           label='Train Error')
 
    plt.ylim([0,200])
    plt.legend()
    plt.show()
 
plot_history(result)

输出结果:

image.png

1.5 实验总结

本实验利用全连接网络完成了汽车油耗里程数预测的任务。重点理解在分类任务和回归任务中,网络模型架构的不同。最后,利用训练返回值中的相关参数,学习在训练中,模型状态的变化,从而深入理解网络训练过程。

posted @ 2021-12-30 19:45  MS小白  阅读(159)  评论(0)    收藏  举报