30天吃掉tensorflow 2.0的总结

这篇博客算是我对自己能力的备忘录,以后使用TF2.0框架,正常情况下,就使用这篇博客内容去调

这篇博客主要描述了模型搭建、管道创建、不同训练模式、不同优化器、不同损失器、不同指标、不同的衡量标准

这里用泰坦尼克号的数据为例作为练习。

第三方库读取

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import models,layers

数据读取

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

EDA分析

%matplotlib inline
%config InlineBackend.figure_format = 'png'
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()

%matplotlib inline
%config InlineBackend.figure_format = 'png'
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()

%matplotlib inline
%config InlineBackend.figure_format = 'png'
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()

数据预处理

def preprocessing(dfdata):

    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)

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

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

    #SibSp,Parch,Fare
    dfresult['SibSp'] = dfdata['SibSp']
    dfresult['Parch'] = dfdata['Parch']
    dfresult['Fare'] = dfdata['Fare']

    #Carbin
    dfresult['Cabin_null'] =  pd.isna(dfdata['Cabin']).astype('int32')

    #Embarked
    dfEmbarked = pd.get_dummies(dfdata['Embarked'],dummy_na=True)
    dfEmbarked.columns = ['Embarked_' + str(x) for x in dfEmbarked.columns]
    dfresult = pd.concat([dfresult,dfEmbarked],axis = 1)

    return(dfresult)

x_train = preprocessing(dftrain_raw)
y_train = dftrain_raw['Survived'].values

x_test = preprocessing(dftest_raw)
y_test = dftest_raw['Survived'].values

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

这里我要插一嘴,因为感觉由于pandas等等库非常非常强大,所以不太需要使用TF内置的特征处理结果,我一般都是把数据用各种模型预处理转换成list/array等格式以后,再用管道搭建直接加载

管道搭建

BATCH_SIZE=32
ds_train = tf.data.Dataset.from_tensor_slices((x_train,y_train)) \
          .shuffle(buffer_size = 1000).batch(BATCH_SIZE) \
          .prefetch(tf.data.experimental.AUTOTUNE).cache()
ds_test = tf.data.Dataset.from_tensor_slices((x_test,y_test)) \
          .shuffle(buffer_size = 1000).batch(BATCH_SIZE) \
          .prefetch(tf.data.experimental.AUTOTUNE).cache()

模型创建

不同激活函数

# relu
tf.keras.backend.clear_session()

model = models.Sequential()
model.add(layers.Dense(20,activation = 'relu',input_shape=(15,)))
model.add(layers.Dense(10,activation = 'relu' ))
model.add(layers.Dense(1,activation = 'sigmoid' ))

model.summary()

# tanh
# tf.keras.backend.clear_session()

# model = models.Sequential()
# model.add(layers.Dense(20,activation = 'relu',input_shape=(15,)))
# model.add(layers.Dense(10,activation = 'tanh' ))
# model.add(layers.Dense(1,activation = 'sigmoid' ))

# model.summary()

# leaky_relu
#tf.keras.backend.clear_session()

# model = models.Sequential()
# model.add(layers.Dense(20,activation = 'relu',input_shape=(15,)))
# model.add(layers.Dense(10,activation=tf.nn.leaky_relu))
# model.add(layers.Dense(1,activation = 'sigmoid' ))

# model.summary()

# elu
#tf.keras.backend.clear_session()

# model = models.Sequential()
# model.add(layers.Dense(20,activation = 'relu',input_shape=(15,)))
# model.add(layers.Dense(10,activation=tf.nn.elu))
# model.add(layers.Dense(1,activation = 'sigmoid' ))

# model.summary()

#selu
#tf.keras.backend.clear_session()

# model = models.Sequential()
# model.add(layers.Dense(20,activation = 'relu',input_shape=(15,)))
# model.add(layers.Dense(10,activation=tf.nn.selu))
# model.add(layers.Dense(1,activation = 'sigmoid' ))

# model.summary()

# swish
# tf.keras.backend.clear_session()

# model = models.Sequential()
# model.add(layers.Dense(20,activation = 'relu',input_shape=(15,)))
# model.add(layers.Dense(10,activation=tf.nn.swish))
# model.add(layers.Dense(1,activation = 'sigmoid' ))

# model.summary()



模型加速

#GPU设置
gpus = tf.config.list_physical_devices("GPU")

if gpus:
    gpu0 = gpus[0] #如果有多个GPU,仅使用第0个GPU
    tf.config.experimental.set_memory_growth(gpu0, True) #设置GPU显存用量按需使用
    # 或者也可以设置GPU显存为固定使用量(例如:4G)
    #tf.config.experimental.set_virtual_device_configuration(gpu0,
    #    [tf.config.experimental.VirtualDeviceConfiguration(memory_limit=4096)]) 
    tf.config.set_visible_devices([gpu0],"GPU") 

模型训练

训练方式1

不同的优化器

# adam
# 二分类问题选择二元交叉熵损失函数
model.compile(optimizer='adam',
            loss='binary_crossentropy',
            metrics=['AUC','accuracy'])
#sgd
# model.compile(optimizer='sgd',
#             loss='binary_crossentropy',
#             metrics=['AUC','accuracy'])

#adagrad
# model.compile(optimizer='adagrad',
#             loss='binary_crossentropy',
#             metrics=['AUC','accuracy'])

#rmsprop
# model.compile(optimizer='rmsprop',
#             loss='binary_crossentropy',
#             metrics=['AUC','accuracy'])

#adadelta
# model.compile(optimizer='adadelta',
#             loss='binary_crossentropy',
#             metrics=['AUC','accuracy'])

#nadam
# model.compile(optimizer='nadam',
#             loss='binary_crossentropy',
#             metrics=['AUC','accuracy'])

开始训练,启动各种配套CallBack

import os
import datetime

# optimizer = tf.keras.optimizers.Adam(learning_rate=0.01)
# model.compile(optimizer=optimizer,loss=MSPE(name = "MSPE"))

stamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
logdir = os.path.join('data', 'autograph', stamp)

## 在 Python3 下建议使用 pathlib 修正各操作系统的路径
# from pathlib import Path
# stamp = datetime.datetime.now().strftime("%Y%m%d-%H%M%S")
# logdir = str(Path('./data/autograph/' + stamp))

tb_callback = tf.keras.callbacks.TensorBoard(logdir, histogram_freq=1)
#如果loss在100个epoch后没有提升,学习率减半。
lr_callback = tf.keras.callbacks.ReduceLROnPlateau(monitor="auc",factor = 0.5, patience = 50)
#当loss在200个epoch后没有提升,则提前终止训练。
stop_callback = tf.keras.callbacks.EarlyStopping(monitor = "auc", patience= 100)

# 在每个训练期之后保存模型
save_dir = os.path.join(os.getcwd(), 'saved_models')
filepath="model_{epoch:02d}-{val_acc:.2f}.hdf5"
# mc_callback=
# tf.keras.callbacks.ModelCheckpoint(os.path.join(save_dir, filepath)
#                                    , monitor='val_loss',
#                                    verbose=0, save_best_only=False,
#                                    save_weights_only=False,
#                                    mode='auto', period=1)
mc_callback=tf.keras.callbacks.ModelCheckpoint(filepath='./model/weights20210521.hdf5',
                            monitor='val_auc',
                            verbose=1, save_best_only=True)
# 把训练轮结果数据流到 csv 文件的回调函数。
csv_callback=tf.keras.callbacks.CSVLogger('training.log')

callbacks_list = [tb_callback,lr_callback,stop_callback,mc_callback,csv_callback]

history = model.fit(ds_train,validation_data = ds_test,epochs = 300,callbacks = callbacks_list)

模型部署保存

## 将模型保存成pb格式文件
export_path = "./model/ExcelData/"
version = "2"       #后续可以通过版本号进行模型版本迭代与管理
model.save(export_path+version, save_format="tf") 

训练方式2

import numpy as np 
import pandas as pd 
import tensorflow as tf
from tensorflow.keras import * 

#打印时间分割线
@tf.function
def printbar():
    today_ts = tf.timestamp()%(24*60*60)

    hour = tf.cast(today_ts//3600+8,tf.int32)%tf.constant(24)
    minite = tf.cast((today_ts%3600)//60,tf.int32)
    second = tf.cast(tf.floor(today_ts%60),tf.int32)
    
    def timeformat(m):
        if tf.strings.length(tf.strings.format("{}",m))==1:
            return(tf.strings.format("0{}",m))
        else:
            return(tf.strings.format("{}",m))
    
    timestring = tf.strings.join([timeformat(hour),timeformat(minite),
                timeformat(second)],separator = ":")
    tf.print("=========="*7+timestring)
def train_model(model,ds_train,ds_valid,epoches):

    for epoch in tf.range(1,epoches+1):
        model.reset_metrics()
        
        # 在后期降低学习率
        if epoch == 400:
            model.optimizer.lr.assign(model.optimizer.lr/2.0)
            tf.print("Lowering optimizer Learning Rate...\n\n")
        
        for x, y in ds_train:
            train_result = model.train_on_batch(x, y)

        for x, y in ds_valid:
            valid_result = model.test_on_batch(x, y,reset_metrics=False)
            
        if epoch%1 ==0:
            printbar()
            tf.print("epoch = ",epoch)
            print("train:",dict(zip(model.metrics_names,train_result)))
            print("valid:",dict(zip(model.metrics_names,valid_result)))
            print("")
model.compile(optimizer='nadam',
            loss='hinge',
            metrics=['AUC','accuracy'])
train_model(model,ds_train,ds_test,500)

训练方式3

optimizer = optimizers.Adam()
loss_func = losses.BinaryCrossentropy()

train_loss = metrics.Mean(name='train_loss')
train_metric = metrics.BinaryCrossentropy(name='train_accuracy')

valid_loss = metrics.Mean(name='valid_loss')
valid_metric = metrics.BinaryCrossentropy(name='valid_accuracy')

@tf.function
def train_step(model, features, labels):
    with tf.GradientTape() as tape:
        predictions = model(features,training = True)
        loss = loss_func(labels, predictions)
    gradients = tape.gradient(loss, model.trainable_variables)
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))

    train_loss.update_state(loss)
    train_metric.update_state(labels, predictions)
    

@tf.function
def valid_step(model, features, labels):
    predictions = model(features)
    batch_loss = loss_func(labels, predictions)
    valid_loss.update_state(batch_loss)
    valid_metric.update_state(labels, predictions)
    

def train_model(model,ds_train,ds_valid,epochs):
    for epoch in tf.range(1,epochs+1):
        
        for features, labels in ds_train:
            train_step(model,features,labels)

        for features, labels in ds_valid:
            valid_step(model,features,labels)

        logs = 'Epoch={},Loss:{},Accuracy:{},Valid Loss:{},Valid Accuracy:{}'
        
        if epoch%1 ==0:
            printbar()
            tf.print(tf.strings.format(logs,
            (epoch,train_loss.result(),train_metric.result(),valid_loss.result(),valid_metric.result())))
            tf.print("")
            
        train_loss.reset_states()
        valid_loss.reset_states()
        train_metric.reset_states()
        valid_metric.reset_states()

train_model(model,ds_train,ds_test,30)
# ## 将模型保存成pb格式文件
# export_path = "./data/yingjun2/1-1"
# version = "3"       #后续可以通过版本号进行模型版本迭代与管理
# model.save(export_path+version, save_format="tf") 

结果可视化

%matplotlib inline
%config InlineBackend.figure_format = 'svg'

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")

plot_metric(history,"auc")

plot_metric(history,"accuracy")

表格解析

import pandas as pd 
dfhistory = pd.DataFrame(history.history)
dfhistory.index = range(1,len(dfhistory) + 1)
dfhistory.index.name = 'epoch'

dfhistory

模型保存

普通的

# 保存模型结构及权重

model.save('./data/keras_model20201111.h5')  

del model  #删除现有模型

# identical to the previous one
model = models.load_model('./data/keras_model20201111.h5')

# 保存模型结构
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)

原生TF保存的

# 保存权重,该方式仅仅保存权重张量
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)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南楚巫妖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值