深度学习工具实践——TensorFlow2.0

概述:深度学习工具实践——TensorFlow2.0

1.基本语法

1
2
3
4
5
6
7
# 查看版本
import tensorflow as tf
tf.__version__
# 无关信息是CPP写出的,0全部打印,2只打印error信息
import os
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'

2.构建单层感知机

预测f(x)=ax+b

2.1导入库

1
2
3
4
import pandas as pd
import numpy as np
import random
import matplotlib.pyplot as plt

2.2生成数据

1
2
x = np.arange(1,30)
y = list(i * 2 + np.random.random()*10 for i in x)

2.3数据可视化

1
2
plt.scatter(x,y)
plt

2.4创建神经网络

1
2
3
model = tf.keras.Sequential()#顺序模型
model.add(tf.keras.layers.Dense(1,input_shape=(1,)))#Dense(输出维度,输入维度)
model.summary()#输出神经网络模型结构
1
2
3
4
5
6
7
8
9
10
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
dense (Dense) (None, 1) 2
=================================================================
Total params: 2
Trainable params: 2
Non-trainable params: 0
_________________________________________________________________

2.5编译神经网络

1
model.compile(optimizer='adam',loss='mse')#优化器:adam,其默认学习率:0.001

2.6拟合/训练神经网络

1
history = model.fit(x,y,epochs=10000,verbose=0)#其中epochs表示对所有数据训练的次数,verbose为0表示不显示训练过程

3.构建多层感知机

f(x1,x2)=ax1+bx2+c

3.1导入库

1
2
3
4
5
import tensorflow as tf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

3.2生成数据

1
2
3
4
x1 = np.arange(1,30)
x2 = list(i * np.random.random()*10 for i in x1)
y = list(i * 2 + np.random.random()*10 for i in x1 + x2)
x = np.reshape(np.array([x1,x2]),(-1,2))

3.3数据可视化

1
plt.scatter(x1,y)

3.4创建神经网络

1
2
model = tf.keras.Sequential([tf.keras.layers.Dense(10,input_shape=(2,),activation='relu'),tf.keras.layers.Dense(1)])
model.summary()#输出模型结构

3.5编译神经网络

1
model.compile(optimizer='adam',loss='mse')

3.6训练神经网络

1
model.fit(x,y,epochs=100,verbose=0)

4.实现逻辑回归(二分类)

4.1导入库

1
2
3
4
5
import tensorflow as tf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

4.2生成数据

1
2
3
4
5
6
x1 = np.arange(1,30)
x2 = list(i * np.random.random()*10 for i in x1)
x = np.reshape(np.array([x1,x2]),(-1,2))
y = list(i * 2 + np.random.random()*10 for i in x1 + x2)
for i in range(len(y)):#分类指标
y[i] = 1 if y[i] > 100 else 0

4.3创建神经网络

1
2
3
4
5
model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(4,input_shape=(2,),activation='relu'))#第一层隐藏层
model.add(tf.keras.layers.Dense(4,activation='relu'))#第二层隐藏层不需要input_shape,会自动推断
model.add(tf.keras.layers.Dense(1,activation='sigmoid'))#输出层
model.summary()#结构可视化

4.4编译神经网络

1
model.compile(optimizer='adam',loss='binary_crossentropy',metrics=['accuracy'])#选择accuracy作为度量标准

4.5训练神经网络

1
history = model.fit(x,y,epochs=1000,verbose=0)

4.6查看训练过程中损失和准确度曲线

1
history.history.keys()
1
2
# 返回history.history的关键字
>> dict_keys(['loss', 'accuracy'])
1
plt.plot(history.epoch,history.history.get('loss'))#loss曲线

1
plt.plot(history.epoch,history.history.get('accuracy'))#acc曲线

5.实现

结合TF自带数据集实现神经网络

5.1 导入库

1
2
3
4
5
6
import tensorflow as tf
import tensorflow.keras as keras
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

5.2 导入TF的FashionMnist数据

1
2
# 是传统MNIST手写字体数据库的加强版(鞋子、衣服、裤子等)
(train_image,train_label),(test_image,test_label) = tf.keras.datasets.fashion_mnist.load_data()#可能涉及翻Q

5.3 查看图像数据形状/可视化

1
train_image.shape,train_label.shape
1
2
#返回结果
>> ((60000, 28, 28), (60000,))
1
plt.imshow(train_image[0])#对图像可视化

5.4图像数据归一化

1
np.max(train_image[0]),np.min(train_image[0])#查看图像数据值范围
1
2
#返回结果
>> (255, 0)
1
2
3
#最值归一化(0-1)
train_image = train_image/255
test_image = test_image/255

5.5创建神经网络

1
2
3
4
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28)))#扁平层==>28*28
model.add(tf.keras.layers.Dense(128,activation='relu'))#隐藏层
model.add(tf.keras.layers.Dense(10,activation='softmax'))#输出层

5.6编译神经网络

1
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])

数值编码多分类使用:sparse_categorical_crossentropy

Onehot编码多分类使用:categorical_crossentropy

5.7训练神经网络

1
model.fit(train_image,train_label,epochs=10)

5.8验证神经网络

1
model.evaluate(test_image,test_label)#验证模型
1
2
#返回结果(损失值loss,准确度accuracy)
>> [0.33301281309127806, 0.883]

5.9 对标签Onehot处理

1
2
3
train_label_onehot = tf.keras.utils.to_categorical(train_label)
test_label_onehot = tf.keras.utils.to_categorical(test_label)
train_label_onehot
1
2
3
4
5
6
7
8
# 返回结果
array([[0., 0., 0., ..., 0., 0., 1.],
[1., 0., 0., ..., 0., 0., 0.],
[1., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[1., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]], dtype=float32)

5.10创建、编译、训练、验证神经网络

1
2
3
4
5
6
7
8
9
10
11
model = tf.keras.Sequential()

model.add(tf.keras.layers.Flatten(input_shape=(28,28)))#扁平层
model.add(tf.keras.layers.Dense(128,activation='relu'))#隐藏层
model.add(tf.keras.layers.Dense(10,activation='softmax'))#输出层

model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])

history = model.fit(train_image,train_label_onehot,epochs=10,validation_data=(test_image,test_label_onehot))

model.evaluate(test_image,test_label_onehot)#验证模型

5.11查看训练过程损失和准确度曲线

1
2
3
4
5
history.history.keys()
#损失值曲线
plt.plot(history.epoch,history.history.get('loss'),label='loss')
plt.plot(history.epoch,history.history.get('val_loss'),label='val_loss')
plt.legend()

1
2
3
4
#准确度曲线
plt.plot(history.epoch,history.history.get('accuracy'),label='accuracy')
plt.plot(history.epoch,history.history.get('val_accuracy'),label='val_accuracy')
plt.legend()

5.12神经网络中加入dropout训练

训练过程中随机丢弃部分神经单元,测试不丢弃,避免神经网络过拟合,减少神经元之间复杂共适应关系,dropout导致两个神经元不一定每次都在一个dropout网络出现,权值更新不再依赖固定关系的隐含节点的共同作用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#创建神经网络
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28)))#扁平层
model.add(tf.keras.layers.Dense(128,activation='relu'))#隐藏层
model.add(tf.keras.layers.Dropout(0.2))#Dropout层
model.add(tf.keras.layers.Dense(128,activation='relu'))#隐藏层
model.add(tf.keras.layers.Dropout(0.2))#Dropout层
model.add(tf.keras.layers.Dense(10,activation='softmax'))#输出层
#编译神经网络
model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])
#训练神经网络
history = model.fit(train_image,train_label_onehot,epochs=10,validation_data=(test_image,test_label_onehot))
#训练过程可视化
plt.plot(history.epoch,history.history.get('accuracy'),label='accuracy')
plt.plot(history.epoch,history.history.get('val_accuracy'),label='val_accuracy')
plt.legend()

6.函数式API搭建神经网络

6.1导入库

1
2
3
4
5
6
import tensorflow as tf
import tensorflow.keras as keras
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

6.2数据集预处理

1
2
3
4
5
6
7
8
# 数据加载
(train_image,train_label),(test_image,test_label) = tf.keras.datasets.fashion_mnist.load_data()
# 数据归一化
train_image = train_image/255
test_image = test_image/255
# 数据形状
train_image.shape,train_label.shape
# ((60000, 28, 28), (60000,))

6.3搭建神经网络

1
2
3
4
5
6
7
8
9
10
11
# 单层网络搭建
input = keras.Input(shape=(28,28))
x = keras.layers.Flatten()(input)
x = keras.layers.Dense(32,activation='relu')(x)
x = keras.layers.Dropout(0.5)(x)
x = keras.layers.Dense(64)(x)
output = keras.layers.Dense(10,activation='softmax')(x)
# 确定输入输出
model = keras.Model(inputs=input,outputs=output)
# 网络结构可视化
model.summary()

6.4 编译、训练神经网络

1
2
3
model.compile(optimizer='adam',loss='sparse_categorical_crossentropy',metrics=['accuracy'])

model.fit(train_image,train_label,epochs=10,batch_size=32)

7.基于MNIST构建卷积神经网络

7.1导入库

1
2
3
4
5
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt
print(tf.__version__)

7.2 数据预处理

1
2
3
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape((-1,28,28,1))
x_test = x_test.reshape((-1,28,28,1))

7.3 搭建神经网络

1
2
3
4
5
6
7
8
9
10
11
model = keras.Sequential()
# 卷积层
model.add(layers.Conv2D(input_shape=(x_train.shape[1], x_train.shape[2], x_train.shape[3]), filters=32, kernel_size=(3,3), strides=(1,1), padding='valid', activation='relu'))
# 池化层
model.add(layers.MaxPool2D(pool_size=(2,2)))
# 平坦层
model.add(layers.Flatten())
# 全连接层
model.add(layers.Dense(32, activation='relu'))
# 输出层
model.add(layers.Dense(10, activation='softmax'))

7.4 编译神经网络

1
model.compile(optimizer=keras.optimizers.Adam(),loss=keras.losses.SparseCategoricalCrossentropy(),metrics=['accuracy'])

其中loss=keras.losses.CategoricalCrossentropy(), 需要使用to_categorical操作,即Onehot预处理

7.5 结构可视化

1
model.summary()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 返回结果
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
conv2d (Conv2D) (None, 26, 26, 32) 320
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 13, 13, 32) 0
_________________________________________________________________
flatten (Flatten) (None, 5408) 0
_________________________________________________________________
dense (Dense) (None, 32) 173088
_________________________________________________________________
dense_1 (Dense) (None, 10) 330
=================================================================
Total params: 173,738
Trainable params: 173,738
Non-trainable params: 0
_________________________________________________________________

7.6训练网络和训练过程可视化

1
2
3
4
5
6
7
# 训练网络
history = model.fit(x_train, y_train, batch_size=64, epochs=5, validation_split=0.1)
# 过程可视化
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.legend(['training', 'valivation'], loc='upper left')
plt.show()

7.7评估神经网络

1
res = model.evaluate(x_test, y_test)
1
2
# 返回结果
>> 10000/10000 [====] - 1s 80us/sample - loss: 0.0986 - accuracy: 0.9753

7.8实现预测

1
prediction = model.predict(x_test)

8.基于IMDB构建循环神经网络RNN

8.1导入库

1
2
3
4
5
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt
tf.__version__

8.2数据预处理

1
2
3
4
5
6
7
num_words = 30000
maxlen = 200
(x_train, y_train), (x_test, y_test) = keras.datasets.imdb.load_data(num_words=num_words)
x_train = keras.preprocessing.sequence.pad_sequences(x_train, maxlen, padding='post')
x_test = keras.preprocessing.sequence.pad_sequences(x_test, maxlen, padding='post')
print(x_train.shape, ' ', y_train.shape)# (25000, 200) (25000,)
print(x_test.shape, ' ', y_test.shape)# (25000, 200) (25000,)

8.3构建神经网络

1
2
3
4
5
6
model = keras.Sequential([
layers.Embedding(input_dim=30000, output_dim=32, input_length=maxlen),
layers.SimpleRNN(32, return_sequences=True),
layers.SimpleRNN(1, activation='sigmoid', return_sequences=False)
])
model.summary()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 返回结果
Model: "sequential"
_________________________________________________________________
Layer (type) Output Shape Param #
=================================================================
embedding (Embedding) (None, 200, 32) 960000
_________________________________________________________________
simple_rnn (SimpleRNN) (None, 200, 32) 2080
_________________________________________________________________
simple_rnn_1 (SimpleRNN) (None, 1) 34
=================================================================
Total params: 962,114
Trainable params: 962,114
Non-trainable params: 0
_________________________________________________________________

8.4编译神经网络

1
model.compile(optimizer=keras.optimizers.Adam(),loss=keras.losses.BinaryCrossentropy(),metrics=['accuracy'])

8.5训练神经网络

1
2
%%time#计算该小模块运算时间:结果返回 Wall time: 2min 37s
history = model.fit(x_train, y_train, batch_size=64, epochs=5,validation_split=0.1)

8.6绘制训练过程的准确度曲线

1
2
3
4
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.legend(['training', 'valivation'], loc='upper left')
plt

9.基于IMDB构建长短期记忆神经网络LSTM

9.1导入库

1
2
3
4
5
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import matplotlib.pyplot as plt
tf.__version__

9.2数据预处理

1
2
3
4
5
6
7
num_words = 30000
maxlen = 200
(x_train, y_train), (x_test, y_test) = keras.datasets.imdb.load_data(num_words=num_words)
x_train = keras.preprocessing.sequence.pad_sequences(x_train, maxlen, padding='post')
x_test = keras.preprocessing.sequence.pad_sequences(x_test, maxlen, padding='post')
print(x_train.shape, ' ', y_train.shape)# (25000, 200) (25000,)
print(x_test.shape, ' ', y_test.shape)# (25000, 200) (25000,)

9.3构建神经网络

1
2
3
4
5
model = keras.Sequential([
layers.Embedding(input_dim=30000, output_dim=32, input_length=maxlen),
layers.LSTM(32, return_sequences=True),
layers.LSTM(1, activation='sigmoid', return_sequences=False)
])

9.4编译神经网络

1
model.compile(optimizer=keras.optimizers.Adam(),loss=keras.losses.BinaryCrossentropy(),metrics=['accuracy'])

9.5训练神经网络

1
2
%%time
history = model.fit(x_train, y_train, batch_size=64, epochs=5,validation_split=0.1)

9.6绘制训练过程的准确度曲线

1
2
3
4
plt.plot(history.history['accuracy'])
plt.plot(history.history['val_accuracy'])
plt.legend(['training', 'valivation'], loc='upper left')
plt

10.Tensorflow基本语法

10.1 numpy.ndarray和tensor互转

1
2
3
4
5
6
7
8
# numpy.ndarray转tensor
x = tf.convert_to_tensor(x,dtype=tf.float32)
# tensor转numpy
x = x.numpy()
# 判断变量是否为tensor
tf.is_tensor(x)
# 数据类型转换
x = tf.cast(x,dtype=tf.int32)

10.2 查看tensor形状和类型

1
2
x.shape # (TensorShape([60000, 28, 28])
x.dtype # tf.float32

10.3 将数据生成指定长度batch的迭代器

1
2
3
4
5
# 128长度的batch
train_db = tf.data.Dataset.from_tensor_slices((x,y)).batch(128)
# 转为迭代器类型
train_iter = iter(train_db)
sample = next(train_iter)

10.4 定义tensor变量(初始化w和b)

1
2
3
4
5
6
w1 = tf.Variable(tf.random.truncated_normal([784, 256], stddev=0.1))
b1 = tf.Variable(tf.zeros([256]))
w2 = tf.Variable(tf.random.truncated_normal([256, 128], stddev=0.1))
b2 = tf.Variable(tf.zeros([128]))
w3 = tf.Variable(tf.random.truncated_normal([128, 10], stddev=0.1))
b3 = tf.Variable(tf.zeros([10]))

10.5 生成tensor变量/常量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 正态分布的tensor:从服从指定正态分布的数值中取出指定个数的值,均值mean,标准差stddev
x= tf.random.normal([4,25,8],mean=0.0,stddev=1.0)
# 截断正态分布的tensor:从服从指定正态分布的数值中取出指定个数的值,均值mean,标准差stddev,且保留[mean-2×stddev,mean+2×stddev]范围内的随机数
x= tf.random.truncated_normal([4,25,8],mean=0.0,stddev=1.0)
# 生成全0的tensor
tf.zeros([2, 3], tf.int32)
# 生成全1的tensor
tf.ones([2, 3], tf.int32)
# 生成形状相同的tensor
tensor=[[1, 2, 3], [4, 5, 6]]
x1 = tf.ones_like(tensor)
x2 = tf.zeros_like(tensor)
# 生成指定值的tensor
x = tf.fill([2,2],2)
# 生成常量
x = tf.constant([1,2,3,4,5,6],shape=[3,2])
# 定义递增tensor
x = tf.range(5)
#<tf.Tensor: id=328, shape=(5,), dtype=int32, numpy=array([0, 1, 2, 3, 4])>

10.6 维度变换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 添加tensor维度
x.shape # (4, 25, 8)
tf.expand_dims(x,axis=0).shape #添加第一维度,TensorShape([1, 4, 25, 8])
# tensor维度交换——转置
tf.transpose(x).shape
# tensor维度交换——指定维度间转置(将第一维度和第二维度互换)
tf.transpose(a,perm=[1,0,2])
# 减少tensor维度
# 默认第一维
tf.squeeze(x)
# 指定维度(删除第三维)
tf.squeeze(b,axis=2)
# 指定扩展维度
x = tf.ones([3,4])
tf.broadcast_to(x,[2,3,4])
# 复制维度
x.shape # (1,3,4)
x = tf.tile(x,[2,1,1])# 将第一维度复制2遍
x.shape # (2,3,4)

10.7 broadcasting机制

通常在tensor相加采取broadcasting机制,即从右往左匹配,维度不够则复制对应维数,例如:

[4,16,16,32] + [32] 出现维度不匹配

① [32] →[1,1,1,32] → [4,16,16,32]

② [4,16,16,32] + [4,16,16,32] 成功

1
2
3
x = tf.random.normal([4,32,32,3])
y = tf.random.normal([3])
(x+y).shape # TensorShape([(4), (32), (32), (3)])

10.8 tensor内部运算符

1
2
3
4
5
6
7
8
9
10
11
x = tf.math.log(x)#取对数
x = tf.sqrt(x)#开根号
x = tf.square(x)#取平方
val = tf.reduce_sum(x)#求和
val = tf.norm()#求欧基里得范数
val = tf.reduce_mean(x)#求均值
min = tf.reduce_min(x)#最小值
max = tf.reduce_max(x)#最大值
index = tf.argmin(x)#求最小值索引
index = tf.argmax(x)#求最大值索引

10.9 矩阵相乘

1
2
3
4
a = tf.ones([2,2])
b = tf.fill([2,2],3.0)
a@b # 方式一
tf.matmul(a,b)# 方式二

10.10 tensor合并

1
2
3
4
a = tf.ones([4,35,8])
b = tf.ones([2,35,8])
c = tf.concat([a,b],axis=0)
c.shape # TensorShape([6, 35, 8])

10.11 定义tensor静态量

1
x = tf.constant([1,2,3,4],dtype=tf.float32)

10.12 判断tensor对应元素是否相等

1
tf.equal(a,b)

10.13 在一维张量中找到唯一的元素

1
2
x = tf.constant([4,4,1,2,3])
tf.unique(x)# [0, 0, 1, 2, 3]

11.模型子类化

模型子类化中,在init方法中定义网络结构,在 call 方法中定义前向传播,在compute_output_shape方法中定义输出维度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class MyModel(tf.keras.Model):
def __init__(self, num_classes=10):
super(MyModel, self).__init__(name='my_model')
self.num_classes = num_classes
self.layer1 = layers.Dense(32, activation='relu')
self.layer2 = layers.Dense(num_classes, activation='softmax')

def call(self, inputs):
h1 = self.layer1(inputs)
out = self.layer2(h1)
return out

def compute_output_shape(self, input_shape):
shape = tf.TensorShape(input_shape).as_list()
shape[-1] = self.num_classes
return tf.TensorShape(shape)

model = MyModel(num_classes=10)
model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
loss=tf.keras.losses.categorical_crossentropy,
metrics=['accuracy'])

model.fit(train_x, train_y, batch_size=16, epochs=5)

12.保存和读取模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
model.save('model_save.h5')
del model
model = keras.models.load_model('model_save.h5')

# 保存json格式参数
json_string = model.to_json()
print(json_string)
# 写入文件
with open("model.json", "w") as json_file:
json_file.write(json_string)
# 加载和使用
# reinitialized_model = keras.models.model_from_json(json_string)
new_prediction = reinitialized_model.predict(x_test)

# 保存网络结构
config = model.get_config()
# 加载和使用
reinitialized_model = keras.Model.from_config(config)
new_prediction = reinitialized_model.predict(x_test)

# 保存网络参数
weights = model.get_weights()
model.set_weights(weights)

13.自编码器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
encode_input = keras.Input(shape=(28,28,1), name='src_img')
h1 = layers.Conv2D(16, 3, activation='relu')(encode_input)
h1 = layers.Conv2D(32, 3, activation='relu')(h1)
h1 = layers.MaxPool2D(3)(h1)
h1 = layers.Conv2D(32, 3, activation='relu')(h1)
h1 = layers.Conv2D(16, 3, activation='relu')(h1)
encode_output = layers.GlobalMaxPool2D()(h1)

encode_model = keras.Model(inputs=encode_input, outputs=encode_output, name='encoder')
encode_model.summary()

decode_input = keras.Input(shape=(16,), name='encoded_img')
h2 = layers.Reshape((4, 4, 1))(decode_input)
h2 = layers.Conv2DTranspose(16, 3, activation='relu')(h2)
h2 = layers.Conv2DTranspose(32, 3, activation='relu')(h2)
h2 = layers.UpSampling2D(3)(h2)
h2 = layers.Conv2DTranspose(16, 3, activation='relu')(h2)
decode_output = layers.Conv2DTranspose(1, 3, activation='relu')(h2)
decode_model = keras.Model(inputs=decode_input, outputs=decode_output, name='decoder')
decode_model.summary()

autoencoder_input = keras.Input(shape=(28,28,1), name='img')
h3 = encode_model(autoencoder_input)
autoencoder_output = decode_model(h3)
autoencoder = keras.Model(inputs=autoencoder_input, outputs=autoencoder_output,name='autoencoder')
autoencoder.summary()

14.多输入与多输出网络

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 构建一个根据文档内容、标签和标题,预测文档优先级和执行部门的网络
# 超参
num_words = 2000
num_tags = 12
num_departments = 4

# 输入
body_input = keras.Input(shape=(None,), name='body')
title_input = keras.Input(shape=(None,), name='title')
tag_input = keras.Input(shape=(num_tags,), name='tag')

# 嵌入层
body_feat = layers.Embedding(num_words, 64)(body_input)
title_feat = layers.Embedding(num_words, 64)(title_input)

# 特征提取层
body_feat = layers.LSTM(32)(body_feat)
title_feat = layers.LSTM(128)(title_feat)
features = layers.concatenate([title_feat,body_feat, tag_input])

# 分类层
priority_pred = layers.Dense(1, activation='sigmoid', name='priority')(features)
department_pred = layers.Dense(num_departments, activation='softmax', name='department')(features)


# 构建模型
model = keras.Model(inputs=[body_input, title_input, tag_input],
outputs=[priority_pred, department_pred])
model.summary()
keras.utils.plot_model(model, 'multi_model.png', show_shapes=True)#实现个网络层的输入/输出形状
model.compile(optimizer=keras.optimizers.RMSprop(1e-3),
loss={'priority': 'binary_crossentropy',
'department': 'categorical_crossentropy'},
loss_weights=[1., 0.2])#两个输出两个loss权重

# 载入输入数据
title_data = np.random.randint(num_words, size=(1280, 10))
body_data = np.random.randint(num_words, size=(1280, 100))
tag_data = np.random.randint(2, size=(1280, num_tags)).astype('float32')
# 标签
priority_label = np.random.random(size=(1280, 1))
department_label = np.random.randint(2, size=(1280, num_departments))
# 训练
history = model.fit(
{'title': title_data, 'body':body_data, 'tag':tag_data},
{'priority':priority_label, 'department':department_label},
batch_size=32,
epochs=5
)

其中执行keras.utils.plot_model(model, ‘multi_model.png’, show_shapes=True)可能会遇到以下错误:

1
ImportError: Failed to import pydot. You must install pydot and graphviz for `pydotprint` to work.

解决方法:

1.pip install pydot and graphviz

2.下载graphviz.msi:https://graphviz.gitlab.io/_pages/Download/windows/graphviz-2.38.msi

3.在上述代码前添加,路径基于graphviz的安装地址

1
2
import os
os.environ["PATH"] += os.pathsep + 'C:/Program Files (x86)/Graphviz2.38/bin/'

参考图:

15.共享网络层

1
2
3
4
5
6
7
share_embedding = layers.Embedding(1000, 64)

input1 = keras.Input(shape=(None,), dtype='int32')
input2 = keras.Input(shape=(None,), dtype='int32')

feat1 = share_embedding(input1)
feat2 = share_embedding(input2)

16.自定义网络层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# PART I
# 自定义构建全连接层
class MyDense(layers.Layer):
def __init__(self, units=32):# 定义结构参数(全连接层对应神经元数量即可)
super(MyDense, self).__init__()
self.units = units
def build(self, input_shape):# 定义/初始化参数w和b(随机生成且可训练调整)
self.w = self.add_weight(shape=(input_shape[-1], self.units),
initializer='random_normal',
trainable=True)
self.b = self.add_weight(shape=(self.units,),
initializer='random_normal',
trainable=True)
def call(self, inputs):# 定义前向传播
return tf.matmul(inputs, self.w) + self.b

def get_config(self): # 模型的配置参数(全连接层仅包含神经元数量)
return {'units': self.units}

inputs = keras.Input((4,))# 输入
outputs = MyDense(10)(inputs)# 输出
model = keras.Model(inputs, outputs)# 模型(输入,输出)
config = model.get_config()# 模型配置参数
new_model = keras.Model.from_config(config, custom_objects={'MyDense':MyDense})# 模型读取配置参数

# PART II
# 在自定义网络层调用其他网络层,自定义RNN中调用Dense层
# 定义超参数
time_step = 10
batch_size = 32
hidden_dim = 32
inputs_dim = 5
# 自定义循环神经网络
class MyRnn(layers.Layer):
def __init__(self):
super(MyRnn, self).__init__()
self.hidden_dim = hidden_dim #隐藏层维度
self.projection1 = layers.Dense(units=hidden_dim, activation='relu') #全连接层神经元数量
self.projection2 = layers.Dense(units=hidden_dim, activation='relu') #全连接层神经元数量
self.classifier = layers.Dense(1, activation='sigmoid') #输出层维度
def call(self, inputs):
outs = []
states = tf.zeros(shape=[inputs.shape[0], self.hidden_dim])
for t in range(inputs.shape[1]):
x = inputs[:,t,:]
h = self.projection1(x)
y = h + self.projection2(states)
states = y
outs.append(y)
# print(outs)
features = tf.stack(outs, axis=1)
print(features.shape)
return self.classifier(features)

# 构建网络
inputs = keras.Input(batch_shape=(batch_size, time_step, inputs_dim))
x = layers.Conv1D(32, 3)(inputs)
print(x.shape)
outputs = MyRnn()(x)
model = keras.Model(inputs, outputs)

rnn_model = MyRnn()
_ = rnn_model(tf.zeros((1, 10, 5)))

17.自定义损失和指标

自定义指标只需继承Metric类, 并重写一下函数_init_(self),初始化。

update_state(self,y_true,y_pred,sample_weight = None),它使用目标y_true和模型预测y_pred来更新状态变量。

result(self),它使用状态变量来计算最终结果。

reset_states(self),重新初始化度量的状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# 实现CatgoricalTruePositives指标:计算正确分类为属于给定类的样本数量

class CatgoricalTruePostives(keras.metrics.Metric):
def __init__(self, name='binary_true_postives', **kwargs):
super(CatgoricalTruePostives, self).__init__(name=name, **kwargs)
self.true_postives = self.add_weight(name='tp', initializer='zeros')

def update_state(self, y_true, y_pred, sample_weight=None):
y_pred = tf.argmax(y_pred)
y_true = tf.equal(tf.cast(y_pred, tf.int32), tf.cast(y_true, tf.int32))

y_true = tf.cast(y_true, tf.float32)

if sample_weight is not None:
sample_weight = tf.cast(sample_weight, tf.float32)
y_true = tf.multiply(sample_weight, y_true)

return self.true_postives.assign_add(tf.reduce_sum(y_true))

def result(self):
return tf.identity(self.true_postives)

def reset_states(self):
self.true_postives.assign(0.)


model.compile(optimizer=keras.optimizers.RMSprop(1e-3),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[CatgoricalTruePostives()])

model.fit(x_train, y_train,batch_size=64, epochs=3)

# 以定义网络层的方式添加网络loss
class ActivityRegularizationLayer(layers.Layer):
def call(self, inputs):
self.add_loss(tf.reduce_sum(inputs) * 0.1)
return inputs

inputs = keras.Input(shape=(784,), name='mnist_input')
h1 = layers.Dense(64, activation='relu')(inputs)
h1 = ActivityRegularizationLayer()(h1)
h1 = layers.Dense(64, activation='relu')(h1)
outputs = layers.Dense(10, activation='softmax')(h1)
model = keras.Model(inputs, outputs)
# keras.utils.plot_model(model, 'net001.png', show_shapes=True)

model.compile(optimizer=keras.optimizers.RMSprop(),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()])
model.fit(x_train, y_train, batch_size=32, epochs=1)

# 定义网络层的方式添加要统计的metric
class MetricLoggingLayer(layers.Layer):
def call(self, inputs):
self.add_metric(keras.backend.std(inputs),
name='std_of_activation',
aggregation='mean')
return inputs

inputs = keras.Input(shape=(784,), name='mnist_input')
h1 = layers.Dense(64, activation='relu')(inputs)
h1 = MetricLoggingLayer()(h1)
h1 = layers.Dense(64, activation='relu')(h1)
outputs = layers.Dense(10, activation='softmax')(h1)
model = keras.Model(inputs, outputs)
# keras.utils.plot_model(model, 'net001.png', show_shapes=True)

model.compile(optimizer=keras.optimizers.RMSprop(),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()])
model.fit(x_train, y_train, batch_size=32, epochs=1)
# 直接在model上面加
# 以定义网络层的方式添加要统计的metric
class MetricLoggingLayer(layers.Layer):
def call(self, inputs):
self.add_metric(keras.backend.std(inputs),
name='std_of_activation',
aggregation='mean')
return inputs

inputs = keras.Input(shape=(784,), name='mnist_input')
h1 = layers.Dense(64, activation='relu')(inputs)
h2 = layers.Dense(64, activation='relu')(h1)
outputs = layers.Dense(10, activation='softmax')(h2)
model = keras.Model(inputs, outputs)

model.add_metric(keras.backend.std(inputs),
name='std_of_activation',
aggregation='mean')
model.add_loss(tf.reduce_sum(h1)*0.1)

# keras.utils.plot_model(model, 'net001.png', show_shapes=True)

model.compile(optimizer=keras.optimizers.RMSprop(),
loss=keras.losses.SparseCategoricalCrossentropy(),
metrics=[keras.metrics.SparseCategoricalAccuracy()])
model.fit(x_train, y_train, batch_size=32, epochs=1)

人工搭建神经网络

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
for epoch in range(10): # 设置10个epochs
for step, (x, y) in enumerate(train_db): # 每一个batch批次
# x:[128, 28, 28]
# y:[128]
x = tf.reshape(x, [-1, 28*28])# [batch, 28, 28] => [batch, 28×28]
with tf.GradientTape() as tape: # 梯度带GradientTape
# x: [batch, 28*28]
# w1: [784,256]
# b: [256]
# h1 = x@w1 + b1
# h1 = [b,784]@[784,256]+[256]
# h1 = [b,256]+[256]
# h1 = [b,256]+[b,256]
h1 = x@w1 + tf.broadcast_to(b1, [x.shape[0], 256])
h1 = tf.nn.relu(h1)
# [b, 256] => [b, 128]
h2 = tf.add(h1@w2,b2)
h2 = tf.nn.relu(h2)
# [b, 128] => [b, 10]
out = h2@w3 + b3
# 输出向量: [b, 10]

y_onehot = tf.one_hot(y, depth=10)# y:[b] => [b, 10]

loss = tf.square(y_onehot - out) # mse = mean(sum(y-out)^2)

loss = tf.reduce_mean(loss)# 计算平均误差

# 计算梯度
grads = tape.gradient(loss, [w1, b1, w2, b2, w3, b3])
# print(grads)

# w1 = w1 - lr * w1_grad
w1.assign_sub(lr * grads[0])# 原地更新,保持w1为Variable类型
b1.assign_sub(lr * grads[1])
w2.assign_sub(lr * grads[2])
b2.assign_sub(lr * grads[3])
w3.assign_sub(lr * grads[4])
b3.assign_sub(lr * grads[5])

if step % 100 == 0: # 每一百步输出一次loss
print(epoch, step, 'loss:', float(loss))