TensorFlow2框架使用---中高阶API的使用

Tensorflow中高阶API的使用

1. 构建数据管道

当数据量不大时,我们可以一次全部载入内存中训练;但是如果数据量很大,我们就要考虑将数据分批次载入内存中训练,这个时候就要利用数据管道。构建数据管道的途径有很多,下面介绍几种常见的数据格式构建数据管道的方式。

1.1 numpy的ndarray构建

data=tf.data.Dataset.from_tensor_slices((iris['data'],iris['target']))
# 从data中拿三条数据
for feature,label in data.take(3):
    print(feature,label)

# 设置batch_size=x,每次取出一个batch
for feature,label in data.batch(32):
    print(feature,label)

1.2 从DataFrame构建

data=pd.DataFrame(iris['data'],columns=iris.feature_names)
data=tf.data.Dataset.from_tensor_slices((data.to_dict('list'),iris['target']))

for f,l in data.take(1):
    print(f,l)

1.3 生成器构建

from tensorflow.keras.preprocessing.image import ImageDataGenerator

image_generator=ImageDataGenerator().flow_from_directory("Path")

# 定义一个生成器函数
def generator():
    for f,l in image_generator:
        yield (f,l)
        
data=tf.data.Dataset.from_generator(generator,output_types=(...))

1.4 文本文件构建

# 从cvs文件构建
data=tf.data.experimental.make_csv_dataset(file_pattern="...",label_name="xxx",batch_size=xx)

# 从文本文件构建
data=tf.data.TextLineDataset(filenames="xxx")

1.5 从文件路径构建

data=tf.data.Dataset.list_files("xxx/*.jpg")

2. 构建模型

定义模型有三种方式,顺序式、函数式、自定义,最简单易用的就是顺序式,只需要像搭积木那样对model不停地添加就好;但是如果面对模型具有残差结构或者其他非顺序式结构,这个时候就需要函数式建模方式;自定义建模主要针对某些网络模块需要自己实现,这个时候就利用自定义方式搭建;下面就用iris数据集利用三种不同方式构建模型。

准备工作

import tensorflow as tf
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn import datasets
from tensorflow.keras import models,layers,optimizers,losses
from sklearn.model_selection import train_test_split
import os
from datetime import datetime

os.environ['TF_CPP_MIN_LOG_LEVEL']='1'
plt.rcParams['font.sans-serif']='simhei'
plt.rcParams['axes.unicode_minus']=False


data,target=datasets.load_iris()['data'],datasets.load_iris()['target']
X_train,X_test,y_train,y_test=train_test_split(data,target,test_size=0.3,random_state=0)

def plot_metric(history,metric):
    train_metric=history.history[metric]
    val_metric=history.history['val_'+metric]
    X=[i for i in range(1,len(train_metric)+1)]
    plt.plot(X,train_metric,'bo--',label="train_"+metric)
    plt.plot(X,val_metric,'ro-',label="val_"+metric)
    plt.title("训练-测试"+metric)
    plt.xlabel("Epochs")
    plt.ylabel(metric)
    plt.legend()
    plt.show()

2.1 顺序模型

model1=models.Sequential()
model1.add(layers.Dense(10,input_shape=(4,),activation='relu'))
model1.add(layers.Dense(10,activation='relu'))
model1.add(layers.Dense(3,activation='softmax'))

model1.compile(
    optimizer=optimizers.Adam(0.01),
    loss=losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=['accuracy']
)

model1.summary()

开始训练

logdir1='./model/model1/'+datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback1 = tf.keras.callbacks.TensorBoard(logdir1, histogram_freq=1)

history=model1.fit(
    X_train,y_train,
    validation_data=(X_test,y_test),epochs=20,
    callbacks=[tensorboard_callback1]
)
plot_metric(history,"accuracy")

image-20211227144039534

2.2 函数式模型

inputs=layers.Input(shape=(4,))
branch1=layers.Dense(10,activation='relu')(inputs)
branch1=layers.Dense(10,activation='relu')(branch1)

branch2=layers.Dense(10,activation='relu')(inputs)
branch2=layers.Dense(10,activation='relu')(branch2)

concat=layers.Concatenate()([branch1,branch2])
branch3=layers.Dense(10,activation='relu')(concat)
outputs=layers.Dense(3,activation='softmax')(branch3)

model2=models.Model(inputs=inputs,outputs=outputs)

model2.compile(
    optimizer=optimizers.Adam(0.01),
    loss=losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=['accuracy']
)

model2.summary()

logdir2='./model/model2/'+datetime.now().strftime("%Y%m%d-%H%M%S")
tensorboard_callback2 = tf.keras.callbacks.TensorBoard(logdir2, histogram_freq=1)

history=model2.fit(
    X_train,y_train,
    validation_data=(X_test,y_test),epochs=15,
    callbacks=[tensorboard_callback2]
)

模型有两个分支然后合并,长这个样子

image-20211227145040729

这里只是为了演示非序列式模型,其实这种结构对于这个问题是没有必要的。

image-20211227145159587

2.3 自定义模型

先定义子结构

class Block(layers.Layer):
    def __init__(self,**kwargs):
        super(Block,self).__init__(**kwargs)
        
    def build(self,input_shape):
        self.a=layers.Dense(20,activation='relu')
        self.b=layers.Dense(10,activation='relu')
        super(Block,self).build(input_shape)
        
    def call(self,inputs):
        x=self.a(inputs)
        x=self.b(x)
        return x
    
    def get_config(self):
        config=super(Block,self).get_config()
        return config
# 测试   
block=Block()
block.build(input_shape=(None,4,))
block.compute_output_shape(input_shape=(None,4,))

类似于残差结构,我们可以使用自己自定义的结构来构建模型,不过这样很容易出错,后期网络搭建的时候调试也不方便。

所以我们定义好之后可以先试试输出的shape与我们预期是否一致

image-20211227145712957

然后利用自定义的结构再构建网络

class Model3(models.Model):
    def __init__(self):
        super(Model3,self).__init__()
        
    def build(self,input_shape):
        self.block1=Block()
        self.block2=Block()
        self.dense=layers.Dense(3,activation='softmax')
        super(Model3,self).build(input_shape)
    
    def call(self,x):
        x=self.block1(x)
        x=self.block2(x)
        x=layers.Flatten()(x)
        x=self.dense(x)
        return x
    
model3=Model3()
model3.build(input_shape=(None,4))


model3.compile(
    optimizer=optimizers.Adam(0.01),
    loss=losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=['accuracy']
)


model3.summary()

image-20211227150206895

结束

到这里,关于Tensorflow使用的部分就暂时告一段落了。这个专栏由于更多是为了留给自己复习看的,所以并没有方方面面都涉及到,比如早停、学习率动态调整、常用的卷积层、特征变换……这些很常用但是我没有讲,后期涉及到的时候会慢慢把相关的例子补上。接下来就是pytorch相关的,这个相对于Tensorflow来说还是更简单一点点的,所以尽快过一遍。

猜你喜欢

转载自blog.csdn.net/shelgi/article/details/122172979