在复现了两个官网分类实战以后,这一次的实战是一个回归问题(Regression),代码有点多,感觉第一次看还是有点费力。不过耐心的磨了一天感觉还可以。个人本着遇到啥学到哪的原则,回归问题中遇到的参数大多会给出解释(主要是为了方便自己复习)。好的,接下来看看根据API整理的代码吧。传!送!门!
问题描述&数据集介绍:
这次我们的数据集跟车有关,数据集给出了70年代末到80年代初的汽车信息,我们需要构建一个模型,在给定汽车的气缸,排量,马力,重量啊之类的情况下,给出汽车的燃油效率(MPG)。与之前问题的不同之处在于,这是一个回归问题,而非分类问题。好的,让我们开始吧(▽)。
必要包的导入&数据集准备:
from __future__ import absolute_import,division,print_function,unicode_literals
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
dataset_path = keras.utils.get_file("auto-mpg.data","http://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data")
column_names = ['MPG','Cylinders','Displacement','Horsepower','Weight',
'Acceleration', 'Model Year', 'Origin']
以上是我们这次数据集中汽车设计的关键词名称,包括加速度,重量啊之类的。
然后我们把数据集的csv文件读一下
raw_dataset=pd.read_csv(dataset_path,names=column_names,na_values="?",comment='\t',sep=" ",skipinitialspace=True)
dataset=raw_dataset.copy()
dataset.tail()
可以通过dataset_path读出csv文件所在路径,用记事本打开查看一下。
这里给出读csv文件的注释:(天哪官方给出这个函数的参数将近20个)pd.read_csv(dataset_path,names,na_value,comment,sep)
dataset_path:csv文件所在的路径。
names:关键词序列,按照这个例子来理解,就是重量啊,MPG啊之类的。
na_value:当做无进行处理的值,在文件中用“?”表示的视为空值。
comment:这个参数我也不怎么理解,这个单词先理解为注释吧,他只能是一个符号,视为注释的符号。
sep:间隔符,在这里的csv文件中可以看出就是“ ”。
skipinitialspace:跳过间隔符以后的空格。
为了保护原始数据集,我们不直接使用数据集而是用dataset=raw_dataset.copy()
来进行拷贝。
为了保证数据集的完好,用dataset.tail()
来查看数据集的尾部数据。
这里提一下,tail()中不加参数默认显示5条,括号中可以加正整数。
数据清洗:
dataset=dataset.dropna()
为了让实例得到简化,我们抛弃了包含未知的数据,即包含na_values的数据。(官网把这一步叫做数据清洗——高级感.jpg)
origin=dataset.pop('Origin')
dataset['USA']=(origin==1)*1.0
dataset['Europe']=(origin==2)*1.0
dataset['Japan']=(origin==3)*1.0
dataset.tail()
在关键词中,有一栏叫做Origin(产地),根据资料我们得知,1表示美国车,2表示欧洲车,3表示日本车。嗯,然后我们将它转化为one_hot编码,输入代码就可以看到运行结果了,Origin一栏变成了三栏。
训练集与测试集:
train_dataset =dataset.sample(frac=0.8,random_state=0)
test_dataset=dataset.drop(train_dataset.index)
这里我们把数据集进行八二开(frac=0.8),按顺序(random_state=0)分出训练集,用dataset.drop()
drop出剩余的数据用于测试集。(是不是很形象)
我们的目的是构建一个模型,使得他可以预测汽油消耗效率,所以我们要把第一栏的MPG去掉,才能构建得到训练集与测试集。(就好像把一份有答案的练习盖掉答案一样,就是一份练习了。)
train_stats = train_dataset.describe()
train_stats.pop("MPG")
train_stats = train_stats.transpose()#转置
train_stats
#describe()的作用只是将数据的格式按照表格表示而已,pop就是将这一栏的数据删除,transpose是求转置,最后输出数据看一看效果。
train_labels = train_dataset.pop('MPG')
test_labels = test_dataset.pop('MPG')
为了方便模型的训练,在训练之前我们将所有的数值都先归一化一下,下面是归一化函数(减去总体均值,除以总体方差,就可以使得样本的均值为0,方差为1)。
def norm(x):
return (x-train_stats['mean'])/train_stats['std']
normed_train_data=norm(train_dataset)
normed_test_data=norm(test_dataset)
构建网络:
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
作为输入层,需要设置输入维度的大小,其它层不需要。这里的train_dataset.keys()
就是关键词,重量啊,加速度之类的。
optimizer
使用的算法是RMSprop算法,这个具体也不是很懂,暂时先用着吧。
损失函数采用的是mean square error(均方差),metrics观测的是mean abstract error(平均误差绝对值)和均方差。
model=build_model()
model.summary()
好了(~ ̄▽ ̄)~。
训练模型:
这里我们使用打印点来表示训练的进度,这里的callbacks我也不是太懂,大概就是用于训练过程中的一个反馈吧。
class PrintDot(keras.callbacks.Callback):
def on_epoch_end(self,epoch,logs):
if epoch%100==0:print('')
print('.',end='')
EPOCHS=1000
history=model.fit(
normed_train_data,train_labels,
epochs=EPOCHS,validation_split=0.2,verbose=0,
callbacks=[PrintDot()])
这里的print(‘.’,end=’’)问题不大,end是一个跟换行有关的操作,换行时不适用换行符,而是加上一个空字符串。
callbacks中调用了打点函数,验证集(不是测试集)占比0.2。
好啦,我们可以开始对模型进行测试了。
模型测试:
这里做出了训练轮数与绝对偏差,均值方差的曲线
def plot_history(history):
hist = pd.DataFrame(history.history)
hist['epoch'] = history.epoch
plt.figure()
plt.xlabel('Epoch')
plt.ylabel('Mean Abs Error [MPG]')
plt.plot(hist['epoch'], hist['mae'],
label='Train Error')
plt.plot(hist['epoch'], hist['val_mae'],
label = 'Val Error')
plt.ylim([0,5])
plt.legend()
plt.figure()
plt.xlabel('Epoch')
plt.ylabel('Mean Square Error [MPG]')
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()
plot_history(history)
![在这里插入图片描述](http
s://img-blog.csdnimg.cn/2020012820571852.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDMyMjgyNA==,size_16,color_FFFFFF,t_70)
# 回调调试:
这里我们可以看到,在训练次数超过一定程度时,误差反而上升了,很可能存在overfitting(过拟合),因此我们使用回调函数,让误差在开始上升以前停止。
```python
model=build_model()
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()])
patience=10,意味着在10轮训练中若val_loss(验证集损失)不再下降,停止迭代。
测试集测试:
loss,mae,mse=model.evaluate(normed_test_data,test_labels,verbose=2)
print("Testing set Mean Abs Error:{:5.2f}MPG".format(mae))
好了,终于得到了我们的测试结果,接下来我们把结果用图表表示下。
图表表示:
test_predictions=model.predict(normed_test_data).flatten()
plt.scatter(test_labels,test_predictions)#生成散点图
plt.xlabel('True Value[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]) # _表示实线,后面是画出一条x,y范围限定的线条,只是让图显示的明显一些,与计算无关。
好了,终于好了。。。好累啊。
为了让错误预测的分布明显一些,我们用一个柱状图表示,估计的偏差应该是一个随机变量,因此分布大致应该呈现正态分布。
error = test_predictions - test_labels
plt.hist(error, bins =25)#bin的数目
plt.xlabel("Prediction Error [MPG]")
_ = plt.ylabel("Count")
结语:
这个在做这个实战的时候,理解还是花了一些时间,但总体而言并没有很多的新内容,亮点如下:
1:对过拟合进行了回调处理。
2:作图的函数得到了应用。
3:csv文件的读取以及pop,drop等处理
4:当然还有这是一个回归,而非分类,在回归中,我们把需要预测的一项参数作为label。(都是supervised learning)
一篇博客写下来还是蛮累的。。但是还是有点成就感哈(虽然是照着API来)O(∩_∩)O
有错误希望大家能帮忙指出啊,(。_。)。谢谢!
改了好多次代码,jupyter notebook跑起来应该没有问题的。。。。。。吧