30天吃掉tensorflow2 1_1学习笔记

这里记录下“30天吃掉tensorflow2”这个github上的教学项目的学习笔记,上面的教程很好,而且还自带数据集等等,代码偶尔有些小瑕疵

附上地址https://github.com/lyhue1991/eat_tensorflow2_in_30_days

1-1,结构化数据建模流程范例

一,准备数据

dftrain_raw = pd.read_csv('./data/titanic/train.csv')
dftest_raw = pd.read_csv('./data/titanic/test.csv')
dftrain_raw.head(10)
print(dftrain_raw)
print(type(dftrain_raw))

这一段是通过pd.fead_csv读取csv文件,读取的内容以dataframe格式保存,运行结果如图

Dftrain_raw.headfa方法是返回数据的前10行,以此来判断数据有没有读错

接下来是画图部分,

ax = dftrain_raw['Survived'].value_counts().plot(kind = 'bar',
     figsize = (12,8),fontsize=15,rot = 0)
ax.set_ylabel('Counts',fontsize = 15)
ax.set_xlabel('Survived',fontsize = 15)
plt.show()

首先看drtrain_raw[‘Survived’],这里是通过字段从dataframe中选择数据

这是print(dftrain_raw['Survived'].head(10))的结果,对比下之前的数据

Value_counts这个方法,是将数据元素出现的次数倒叙排序

print(dftrain_raw['Survived'].head(10).value_counts())

接下来是plot这个画图方法,参数比较多也比较复杂,常用的参数是这几个

来源:https://blog.csdn.net/jinlong_xu/article/details/70175107

Set_xlabel这些方法从名字上就能看出来,是给坐标轴打上名字的

这里放一个网站,该网站可在线测试代码,以便快速理解画图代码:

http://kakazai.cn/index.php/Kaka/Python/query/name/set_xlabel

最后运行结果是柱状图

ax = dftrain_raw['Age'].plot(kind = 'hist',bins = 20,color= 'purple',
                    figsize = (12,8),fontsize=15)

ax.set_ylabel('Frequency',fontsize = 15)
ax.set_xlabel('Age',fontsize = 15)
plt.show()

这段代码和之前的大同小异,一样是画图,不过图的类型不一样,结果如下

 

ax = dftrain_raw.query('Survived == 0')['Age'].plot(kind = 'density',
                      figsize = (12,8),fontsize=15)
dftrain_raw.query('Survived == 1')['Age'].plot(kind = 'density',
                      figsize = (12,8),fontsize=15)
ax.legend(['Survived==0','Survived==1'],fontsize = 12)
ax.set_ylabel('Density',fontsize = 15)
ax.set_xlabel('Age',fontsize = 15)
plt.show()

 上面这部分代码是求年龄和生还的相关性

首先.query方法,可以理解为把满足数据条件的dataframe里的数据提出来,然后['Age']在前面的基础上指定需要的列的字段名,

如print(dftrain_raw.query('Survived == 0'))的结果如下

而print(dftrain_raw.query('Survived == 0')['Age'])的结果如下

可以看到,.plot方法就是用提取的数据画图,但数据至少要符合维度标准,如

dftrain_raw.query('Survived == 0').plot(kind = 'density',figsize = (12,8),fontsize=15)这样的语句就会报错

正常运行结果

.legend方法是自定义图例(背景),说白了就是这个东西

接下来是数据预处理

dfresult= pd.DataFrame()

这个语句其实就相当于初始化,dfresult里存的是一个空的dataframe

dfresult= pd.DataFrame()
print("dfresult")
print(dfresult)

 

运行结果:

get_dummies方法是利用pandas实现one hot encode的方法

实验代码

dfresult= pd.DataFrame()
print("dfdata['Pclass']")
print(dfdata['Pclass'])

#Pclass
dfPclass = pd.get_dummies(dfdata['Pclass'])
print("pd.get_dummies")
print(dfPclass)

运行结果

可以看出来,get_dummies是实现onehot-encoding的一种方法,同时保留dataframe的数据类型

这段语句是给列重新命名

实验代码: 

 

dfPclass.columns = ['Pclass_' +str(x) for x in dfPclass.columns ]
print(dfPclass)

结果:

接下来是pd.concat方法,这个方法可以将数据根据不同的轴作简单的融合

pd.concat(objs, axis=0, join='outer', join_axes=None)

参数说明:objs: 融合内容,可以是series,dataframe或者是panel构成的序列lsit

axis: 需要合并链接的轴,0是行,1是列

join:连接的方式 inner,或者outer,即内连接或外连接

实验代码:

dfresult= pd.DataFrame()
#Pclass
dfPclass = pd.get_dummies(dfdata['Pclass'])
dfPclass.columns = ['Pclass_' +str(x) for x in dfPclass.columns ]
dfresult = pd.concat([dfresult,dfPclass],axis = 1)
print(dfresult)

#Sex
dfSex = pd.get_dummies(dfdata['Sex'])
dfresult = pd.concat([dfresult,dfSex],axis = 1)
print(dfresult)

结果:

可以看到两个dataframe融合在一起了

 

接下来是.fillna这个方法

.fillna函数是填补缺失值,查看原始数据会发现age一栏里确实存在确实值,在dataframe中会用NaN占位

接下来是.isna方法,这个方法会返回一个dataframe,其中会用1替换NaN的位置,用0替换非NAN的位置

实验代码:

dfresult['Age_null'] = pd.isna(dfdata['Age']).astype('int32')

print(dfresult['Age_null'])

结果:

.astype方法是返回新的对象,其中的数值转换成指定的格式,如float64转成int32。注意返回的是新的对象,原来对象的格式不会发生改变。

 

接下来是series.values方法,这个方法是将series里的值单独返回出来,series是pandas中的一维数组

实验代码

x_train = preprocessing(dftrain_raw)

y_train = dftrain_raw['Survived'].values

print(dftrain_raw['Survived'])

print(y_train)

结果:

                                                                                                   

 

在这里x_train需要进行预处理函数,而y_train不需要,是因为y_train是作为输入参数x_train的结果,在这个项目里结果就是生或死,不需要其他的参数,所以作为结果的y_train只需要一维就行了 

 

接下来是.shape方法,这个方法可以得到dataframe的维度,如x_train就是712*15

实验代码

print("x_train.shape =", x_train.shape )
print("y_train.shape=",y_train.shape)
print("x_test.shape =", x_test.shape )
print("y_test.shape=",y_test.shape)

实验结果:

二,定义模型

定义模型部分,使用Keras接口有以下3种方式构建模型:使用Sequential按层顺序构建模型,使用函数式API构建任意结构模型,继承Model基类构建自定义模型。

教学代码里选择使用最简单的Sequential,按层顺序模型

tf.keras.backend.clear_session()

这个方法是清除之前存在的tf训练进程,不清除的话内存里还会有之前训练的数据,影响运行

model = models.Sequential()

这部分是调用keras自带的序列模型

model.add方法即向模型里添加层

layers.Dense(20,activation = 'relu',input_shape=(15,))

tf.layers.dense()层参数解释:https://blog.csdn.net/sazass/article/details/86935556

其中20是units,即输出空间的维数,input_shape是输入参数的维度。我的理解是类似于矩阵相乘,a*b,b*c的矩阵才能相乘,因此需要规范输入参数和输出的维度

Activation是激活函数,我对激活函数的理解是,激活函数是为了让输出的结果变化更明显,范围更广。

model.summary()是输出模型总结,可以看到各层的状况

三,训练模型

model.compile(optimizer='adam',
            loss='binary_crossentropy',
            metrics=['AUC'])
history = model.fit(x_train,y_train,
                    batch_size= 64,
                    epochs= 30,
                    validation_split=0.2)

model.compile方法来配置训练时的参数

参考博客:https://blog.csdn.net/yunfeather/article/details/106461754

 

其中adam是优化器的类型,即自适应矩估计,loss是损失函数,这里用的是binary_crossentropy,适用于二分类问题,categorical_crossentropy是分类交叉熵适,用于多分类问题

 

meteics是衡量训练模型好坏标准,这里使用的是AUC

评价指标介绍:https://blog.csdn.net/liming89/article/details/106854661

 

Model.fit方法,其中前两个参数x和y分别对应训练数据的输入和结果标签,batchsize指定进行梯度下降时每个batch包含的样本数。训练时一个batch的样本会被计算一次梯度下降,使目标函数优化一步。Epochs是训练终止时的epoch值,训练将在达到该epoch值时停止,当没有设置initial_epoch时,它就是训练的总轮数,否则训练的总轮数为epochs - inital_epoch。validation_split是0~1之间的浮点数,用来指定训练集的一定比例数据作为验证集。验证集将不参与训练,并在每个epoch结束后测试的模型的指标,如损失函数、精确度等。注意,validation_split的划分在shuffle之前,因此如果你的数据本身是有序的,需要先手工打乱再指定validation_split,否则可能会出现验证集样本不均匀。

参考:https://blog.csdn.net/a1111h/article/details/82148497

 

四,评估模型

import matplotlib.pyplot as plt
def plot_metric(history, metric):
    train_metrics = history.history[metric]
    val_metrics = history.history['val_'+metric]
    epochs = range(1, len(train_metrics) + 1)
    plt.plot(epochs, train_metrics, 'bo--')
    plt.plot(epochs, val_metrics, 'ro-')
    plt.title('Training and validation '+ metric)
    plt.xlabel("Epochs")
    plt.ylabel(metric)
    plt.legend(["train_"+metric, 'val_'+metric])
plt.show()

实验代码:

plot_metric(history,"loss")
train_metrics = history.history[metric]
print("history.history",history.history)
print("train_mertics",train_metrics) 

结果: 

 

 

 可以看到,history里存放的就是训练过程中的数据,如loss等,注意plot_metric(history,"AUC")这段代码会报错,输出history.history后我找到了原因,在history里是auc而不是大写的AUC

Model.evaluate这个方法可以用测试集来评估之前训练的模型的准确度

实验代码:

print("evaluate")
model.evaluate(x = x_test,y = y_test)

结果:

 

五,使用模型

#预测概率
model.predict(x_test[0:10])
#model(tf.constant(x_test[0:10].values,dtype = tf.float32)) #等价写法
#预测类别
model.predict_classes(x_test[0:10])

实验代码:

print("predit",model.predict(x_test[0:10]))
print("predit_class",model.predict_classes(x_test[0:10]))

结果

                                                                                                              

上面分别是分类概率和结果,可以看出来默认的阈值是0.5

 

六,保存模型

Keras方式保存

# 保存模型结构及权重
model.save('./data/keras_model.h5') 

del model  #删除现有模型

# identical to the previous one
model = models.load_model('./data/keras_model.h5')
model.evaluate(x_test,y_test)

# 保存模型结构
json_str = model.to_json()

# 恢复模型结构
model_json = models.model_from_json(json_str)

#保存模型权重
model.save_weights('./data/keras_model_weight.h5')

# 恢复模型结构
model_json = models.model_from_json(json_str)
model_json.compile(
        optimizer='adam',
        loss='binary_crossentropy',
        metrics=['AUC']
    )

# 加载权重
model_json.load_weights('./data/keras_model_weight.h5')
model_json.evaluate(x_test,y_test)

附json_str的内容:

json_model {"class_name": "Sequential", "config": {"name": "sequential", "layers": [{"class_name": "InputLayer", "config": {"batch_input_shape": [null, 15], "dtype": "float32", "sparse": false, "ragged": false, "name": "dense_input"}}, {"class_name": "Dense", "config": {"name": "dense", "trainable": true, "batch_input_shape": [null, 15], "dtype": "float32", "units": 20, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_1", "trainable": true, "dtype": "float32", "units": 10, "activation": "relu", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}, {"class_name": "Dense", "config": {"name": "dense_2", "trainable": true, "dtype": "float32", "units": 1, "activation": "sigmoid", "use_bias": true, "kernel_initializer": {"class_name": "GlorotUniform", "config": {"seed": null}}, "bias_initializer": {"class_name": "Zeros", "config": {}}, "kernel_regularizer": null, "bias_regularizer": null, "activity_regularizer": null, "kernel_constraint": null, "bias_constraint": null}}]}, "keras_version": "2.4.0", "backend": "tensorflow"}

可以看出通过json保存模型,好处是可以在各个平台上通用,但是读取起来也更为繁琐,不仅需要json格式的模型,还需要再读取权重,并设置优化器和损失函数

 

TensorFlow原生方式保存

# 保存权重,该方式仅仅保存权重张量

model.save_weights('./data/tf_model_weights.ckpt',save_format = "tf")

# 保存模型结构与模型参数到文件,该方式保存的模型具有跨平台性便于部署

model.save('./data/tf_model_savedmodel', save_format="tf")
print('export saved model.')

model_loaded = tf.keras.models.load_model('./data/tf_model_savedmodel')
model_loaded.evaluate(x_test,y_test)

可以看出最好直接用model.save方法,这是最方便的

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值