tensorflow2.0實現復雜神經網絡(多輸入多輸出nn,Resnet)
常見的‘融合’操作
復雜神經網絡模型的實現離不開”融合”操作。常見融合操作如下:
(1)求和,求差
# 求和 layers.Add(inputs) # 求差 layers.Subtract(inputs)
inputs: 一個輸入張量的列表(列表大小至少為 2),列表的shape必須一樣才能進行求和(求差)操作。
例子:
input1 = keras.layers.Input(shape=(16,)) x1 = keras.layers.Dense(8, activation='relu')(input1) input2 = keras.layers.Input(shape=(32,)) x2 = keras.layers.Dense(8, activation='relu')(input2) added = keras.layers.add([x1, x2]) out = keras.layers.Dense(4)(added) model = keras.models.Model(inputs=[input1, input2], outputs=out)
(2)乘法
# 輸入張量的逐元素乘積(對應位置元素相乘,輸入維度必須相同) layers.multiply(inputs) # 輸入張量樣本之間的點積 layers.dot(inputs, axes, normalize=False)
dot即矩陣乘法,例子1:
x = np.arange(10).reshape(1, 5, 2) y = np.arange(10, 20).reshape(1, 2, 5) # 三維的輸入做dot通常像這樣指定axes,表示矩陣的第一維度和第二維度參與矩陣乘法,第0維度是batchsize tf.keras.layers.Dot(axes=(1, 2))([x, y]) # 輸出如下: <tf.Tensor: shape=(1, 2, 2), dtype=int64, numpy= array([[[260, 360], [320, 445]]])>
例子2:
x1 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2)) x2 = tf.keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2)) dotted = tf.keras.layers.Dot(axes=1)([x1, x2]) dotted.shape TensorShape([5, 1])
(3)聯合:
# 所有輸入張量通過 axis 軸串聯起來的輸出張量。 layers.add(inputs,axis=-1)
- inputs: 一個列表的輸入張量(列表大小至少為 2)。
- axis: 串聯的軸。
例子:
x1 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2)) x2 = tf.keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2)) concatted = tf.keras.layers.Concatenate()([x1, x2]) concatted.shape TensorShape([5, 16])
(4)統計操作
求均值layers.Average()
input1 = tf.keras.layers.Input(shape=(16,)) x1 = tf.keras.layers.Dense(8, activation='relu')(input1) input2 = tf.keras.layers.Input(shape=(32,)) x2 = tf.keras.layers.Dense(8, activation='relu')(input2) avg = tf.keras.layers.Average()([x1, x2]) # x_1 x_2 的均值作為輸出 print(avg) # <tf.Tensor 'average/Identity:0' shape=(None, 8) dtype=float32> out = tf.keras.layers.Dense(4)(avg) model = tf.keras.models.Model(inputs=[input1, input2], outputs=out)
layers.Maximum()用法相同。
具有多個輸入和輸出的模型
假設要構造這樣一個模型:
(1)模型具有以下三個輸入
工單標題(文本輸入),工單的文本正文(文本輸入),以及用戶添加的任何標簽(分類輸入)
(2)模型將具有兩個輸出:
- 介於 0 和 1 之間的優先級分數(標量 Sigmoid 輸出)
- 應該處理工單的部門(部門范圍內的 Softmax 輸出)。
模型大概長這樣:
接下來開始創建這個模型。
(1)模型的輸入
num_tags = 12 num_words = 10000 num_departments = 4 title_input = keras.Input(shape=(None,), name="title") # Variable-length sequence of ints body_input = keras.Input(shape=(None,), name="body") # Variable-length sequence of ints tags_input = keras.Input(shape=(num_tags,), name="tags") # Binary vectors of size `num_tags`
(2)將輸入的每一個詞進行嵌入成64-dimensional vector
title_features = layers.Embedding(num_words,64)(title_input) body_features = layers.Embedding(num_words,64)(body_input)
(3)處理結果輸入LSTM模型,得到 128-dimensional vector
title_features = layers.LSTM(128)(title_features) body_features = layers.LSTM(32)(body_features)
(4)concatenate融合所有的特征
x = layers.concatenate([title_features, body_features, tags_input])
(5)模型的輸出
# 輸出1,回歸問題 priority_pred = layers.Dense(1,name="priority")(x) # 輸出2,分類問題 department_pred = layers.Dense(num_departments,name="department")(x)
(6)定義模型
model = keras.Model( inputs=[title_input, body_input, tags_input], outputs=[priority_pred, department_pred], )
(7)模型編譯
編譯此模型時,可以為每個輸出分配不同的損失。甚至可以為每個損失分配不同的權重,以調整其對總訓練損失的貢獻。
model.compile( optimizer=keras.optimizers.RMSprop(1e-3), loss={ "priority": keras.losses.BinaryCrossentropy(from_logits=True), "department": keras.losses.CategoricalCrossentropy(from_logits=True), }, loss_weights=[1.0, 0.2], )
(8)模型的訓練
# Dummy input data title_data = np.random.randint(num_words, size=(1280, 10)) body_data = np.random.randint(num_words, size=(1280, 100)) tags_data = np.random.randint(2, size=(1280, num_tags)).astype("float32") # Dummy target data priority_targets = np.random.random(size=(1280, 1)) dept_targets = np.random.randint(2, size=(1280, num_departments)) # 通過字典的形式將數據fit到模型 model.fit( {"title": title_data, "body": body_data, "tags": tags_data}, {"priority": priority_targets, "department": dept_targets}, epochs=2, batch_size=32, )
ResNet 模型
通過add來實現融合操作,模型的基本結構如下:
# 實現第一個塊 _input = keras.Input(shape=(32,32,3)) x = layers.Conv2D(32,3,activation='relu')(_input) x = layers.Conv2D(64,3,activation='relu')(x) block1_output = layers.MaxPooling2D(3)(x) # 實現第二個塊 x = layers.Conv2D(64,3,padding='same',activation='relu')(block1_output) x = layers.Conv2D(64,3,padding='same',activation='relu')(x) block2_output = layers.add([x,block1_output]) # 實現第三個塊 x = layers.Conv2D(64, 3, activation="relu", padding="same")(block2_output) x = layers.Conv2D(64, 3, activation="relu", padding="same")(x) block_3_output = layers.add([x, block2_output]) # 進入全連接層 x = layers.Conv2D(64,3,activation='relu')(block_3_output) x = layers.GlobalAveragePooling2D()(x) x = layers.Dense(256, activation="relu")(x) x = layers.Dropout(0.5)(x) outputs = layers.Dense(10)(x)
模型的定義與編譯:
model = keras.Model(_input,outputs,name='resnet') model.compile( optimizer=keras.optimizers.RMSprop(1e-3), loss='sparse_categorical_crossentropy', metrics=["acc"], )
模型的訓練
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data() # 歸一化 x_train = x_train.astype("float32") / 255 x_test = x_test.astype("float32") / 255 model.fit(tf.expand_dims(x_train,-1), y_train, batch_size=64, epochs=1, validation_split=0.2)
註:當loss = =keras.losses.CategoricalCrossentropy(from_logits=True)時,需對標簽進行one-hot:
y_train = keras.utils.to_categorical(y_train, 10)
到此這篇關於tensorflow2.0實現復雜神經網絡(多輸入多輸出nn,Resnet)的文章就介紹到這瞭,更多相關tensorflow2.0復雜神經網絡內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- Python深度學習之實現卷積神經網絡
- 由淺入深學習TensorFlow MNIST 數據集
- tensorflow2.0教程之Keras快速入門
- python之tensorflow手把手實例講解斑馬線識別實現
- python之tensorflow手把手實例講解貓狗識別實現