以下内容来自b站tf2.0实战视频学习同步笔记

1. 到底是tensorflow2.0 还是1.X

如果没接触过tensorflow1.X,可以直接学习tensorflow2.0

2. 核心高阶API

tf.keras
tf.eager
tf.data
tf.function

3. tf.keras

用tf.keras 训练一个线性回归模型

model = tf.keras.Sequential()
# 增加层
model.add(tf.keras.layers.Dense(1,input_shape=(1,)))  
# 定义好输出和输入
model.summary()

model.compile(optimizer='adam',  # 优化方法,adam优化算法中未规定学习速率,默认为0.001 
			  loss='mse'         # 损失函数
			  )
		  
history = model.fit(x,y,epochs=5)
# epochs表示对所有数据的训练次数

model.predict(x)
model.predict(pd.Series([20]))

4. 多层感知器MLP(神经网络)

单层线性回归无法解决异或问题
接受神经元的启发,在输入端和输出端之间插入更多的神经元
输入层-隐含层-输出层
激活:激活带来非线性,使得网络可以拟合非线性关系
激活函数:

  1. relu: 小于0为0,大于零原样输出
  2. sigmoid: p ( x ) = 1 / ( 1 + e X ) p(x)=1/(1+e^{-X}) p(x)=1/(1+eX)
  3. tanh: 值域趋于 [ 1 , 1 ] [-1,1] [1,1],图像和sigmoid很像,不过零附近的值变化贼快
  4. leak relu 小于零的时候输出很小的值,大于零时候原样输出
model = tf.keras.Sequential([
		tf.keras.layers.Dense(10, input_shape=(3,),activation='relu'),
		tf.keras.layers.Dense(1)])

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

# 建模
model = tf.keras.Sequential()
model.add(tf.keras.layers.Dense(4, input_shape=(15,), activation='relu'))
model.add(tf.keras.layers.Dense(4, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))

model.summary()

# 编译
model.compile(optimizer='adam',
			  loss='binary_crossentropy',   # 交叉熵
			  metrics==['acc'])  # accuracy是列表

# 拟合
history = model.fit(x,y, epochs=100)

history.history # 是个字典,dict 记录了loss和acc
history.history.keys()

# 画图展现loss的变化
plt.plot(history.epoch, history.history.get('loss'))
plt.show()

6 实现逻辑回归(多分类)

softmax实现多分类
tf.keras中使用categorical_crossentropy和sparse_categorical_crossentropy 来计算softmax交叉熵,作为损失函数loss function

6.1 fashion MNIST 数据集

加载

(train_images,train_labels),(test_images,test_labels) = tf.keras.datasets.fashion_mnist.load_data()

归一化:

train_images = train_images / 255.0
tets_images = test_images / 255.0
# 建模
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28))) # 压平后才可喂给dense层
model.add(tf.keras.layers.Dense(128,activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='softmax')) # 长度为10 的概率输出,是多分类,用softmax激活

# 编译
model.comopile(optimizer='adam',
			   loss='sparse_categorical_crossentropy',# 顺序标签
			   metrics=['acc'])

# 拟合
model.fit(train_images, train_labels, epochs=5)

# 评价
model.evaluate(test_images,test_labels)

注意,当label是one-hot编码时,loss应该用categorical_crossentropy;
当label是顺序编码时,loss应该用sparse_categorical_crossentropy

# tf中内置了转化为独热编码的方法
train_label_onehot = tf.keras.utils.to_categorical(train_label)

# 建模
model = tf.keras.Sequential()
model.add(tf.keras.layers.Flatten(input_shape=(28,28))) # 压平后才可喂给dense层
model.add(tf.keras.layers.Dense(128,activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='softmax')) # 长度为10 的概率输出,是多分类,用softmax激活

# 编译
model.comopile(optimizer='adam',
			   loss='categorical_crossentropy',# one-hot标签
			   metrics=['acc'])

# 拟合
model.fit(train_images, train_labels, epochs=5)

# 预测
predict = model.predict(test_images)
# 此时,predict应该是一个长度为num_of_test的每个包含10个元素的array,10个元素表示分类到10类的概率,取最大得到预测结果:

# 得到预测结果
np.argmax(predict[0])  

7. 优化函数、学习速率、反向传播

多层感知器的优化算法是梯度下降法
学习速率:对梯度进行缩放的参数成为学习速率,超参数(写代码时候自己需要事先规定的参数,手工可配置)
查看损失函数虽时间下降的曲线,若震荡,则学习速率不合适,减小下试一试。若不断下降,则证明合适
反向传播算法:高效计算数据流图中梯度的技术,每一层的导数都是后一层的导数与前一层输出之积,链式法则
前馈(由前往后计算损失函数时),从输入开始,逐一计算每个隐含层的输出,直到输出层;然后开始计算导数,并从输出层经各隐含层逐一反向传播。
优化函数:optimizer是编译模型所需要的两个参数之一,常见的有:

  • SGD:随机梯度下降优化器
  • RMSprop: 处理序列问题,文本分类,序列预测,RNN的不错选择;RMSprop增加了一个衰减系数来空值历史信息的获取多少,并会对学习率进行衰减
  • ADAM: 看作是修正后的momentum+RMSprop算法,通常被认为对超参数的选择相当鲁棒,学习率建议为0.001;是一阶优化算法,能自适应的改变学习速率
# 编译优化函数:
model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=0.01)),  # 学习速率
			  loss='sparse_categorical_crossentropy',
			  metrics=['acc'])

# 小技巧:shift+tab可以查看默认参数

8. 网络优化与超参选择

网络中神经元越多,层数越多,神经网络的拟合能力越强
但是训练速度、难度越大,越容易产生过拟合
网络优化:增大网络容量要么增加层,要么增加隐藏神经元个数,增加层会大大提高网络的拟合能力;另外,单层的神经元个数也不能太少,太少会造成信息瓶颈,使得模型欠拟合

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(128, activation='relu'))
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='softmax'))

model.summary()

9. 使用Dropout抑制过拟合

# 增加validation set
history = model.fit(train_images, train_labels,
				    epochs=10,
				    validation_data=(val_images,val_labels))

# 这样会使得history.history变成包含了训练集、验证集loss和acc的字典
history.history.keys()

过拟合:在训练数据上得分很高,在测试数据上得分相对比较低
欠拟合:在训练数据上得分很低,在测试数据上得分更别提了
添加dropout层可以抑制过拟合

参数选择原则:开发一个过拟合模型(增加更多层、每一层变得更强大,训练更多的轮次等),抑制过拟合(增加训练数据,使用小型网络减少网络规模,dropout,正则化,图像增强),调节超参数(学习速率、隐藏层单元数,训练轮次)

# 添加dropout层,抑制过拟合
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.5)) # 每次只激活0.5,随机丢弃50%
model.add(tf.keras.layers.Dense(128, activation='relu'))
model.add(tf.keras.layers.Dropout(0.5)) # 每次只激活0.5,随机丢弃50%
model.add(tf.keras.layers.Dense(10, activation='softmax'))

model.summary()

10. 函数式API

# 也太棒了吧。。
inputs = keras.Input(shape=(28,28)) # 输入形状
x = keras.layers.Flatten()(input)  # 把keras.layers.Flatten()看作是函数,这么酷?
x = keras.layers.Dense(32,activation='relu')(x)
x = keras.layers.Dropout(0.5)(x)
x = keras.layers.Dense(64,activation='relu')(x)
outputs = keras.layers.Dense(10,activation='softmax')(x)


model = keras.Model(inputs=inputs,outputs=outputs)

好处是,可以设置多个输入,如

# 两个输入,判断两幅图片是不是相同,输出为是否,是个逻辑回归
input1 = keras.Input(shape=(28,28))
input2 = keras.Input(shape=(28,28))

X1 = keras.layers.Flatten()(input1)
X2 = keras.layers.Flatten()(input2)

# 合并X1,X2
x = keras.layers.concatenate([X1,X2])

x = keras.layers.Dense(32,activation='relu')(x)
outputs = keras.layers.Dense(1,activation='sigmoid')(x)

model = keras.Model(inputs=[input1,input2],outputs=outputs)