前驱课程: 《吴恩达深度学习》
听完课才有一些专有名词的概念
首先是导库import tensorflow as tf from tensorflow import keras张量设置和使用 创建恒定张量
x = tf.constant([[1,3], [1, 2]]) # 可使用.numpy() 改变type x.numpy()矩阵创建
# 1/0矩阵 tf.ones(shape=(,)) tf.zeros(shape=(,)) # 正态分布 tf.random.normal(shape=(,), mean=, stddev=) # 均匀分布 tf.random.uniform(shape=(,), minval=, maxval=, dtype='int32')变量(用来存储网络权重的)
tf.Variable(m) # m代表矩阵,可以是numpy类型,也可以是张量 # 此类型具有的一些改变的方法 # 1 .assign(value) # 重新设置值,注意:这里的value的shape要和之前的m一致 .assign_add(incre) # 增量incre,注意:这里的incre的shape要和之前的m一致 .assign_sub(decre) # 减量decre,注意:这里的decre的shape要和之前的m一致一些数值计算方法
tf.square(m) # 将矩阵m内元素进行平方 tf.exp(m) # m里边元素i进行e的i次方计算数据切分
# 一般都是从 csv或者excel获取数据 # 切分 dataset = tf.data.Dataset.from_tensor_slices((x,y)) # x,y使用numpy格式就好 # 打乱 dataset = dataset.shuffle(buffer_size=buffer_size).batch(batch_size)使用继承设计自己想要的层(keras.layers.Layer)
# build(),call() 方法的使用 # 初始化器 tf.random_normal_initializer() # 在add_weight()参数中initializer="random_normal" # 查看权重 .weights # 使用这个获取权重示例:
# 需要继承的父类是 keras.layers.Layer
# 先看初级版本的,比较麻烦,而后面的有固定需要的方法能够更方便去使用
class Linear(keras.layers.Layer):
"""
一般全连接层:y = x.w + b
"""
def __init__(self, units=32, input_dim=32):
super(Linear, self).__init__()
init_w = tf.random_normal_initializer() # 初始化器
self.w = tf.Variable(init_w(shape=(input_dim, units),dtype='float32'),
trainable=True)
init_b = tf.zeros_initializer() # 初始化器
self.b = tf.Variable(init_b(shape=(units, ), dtype='float32'),
trainable=True)
def call(self, inputs):
return tf.matmul(x, self.w) + self.b
# 使用add_weight(),在build方法中(自动调用)
class Linear(keras.layers.Layer):
def __init__(self, units):
super(Linear, self).__init__()
self.units = units
def build(self, input_shape):
"""
这里设置各种参数,在使用这个类的时候就会自动执行build。
"""
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 # 最终层的话返回的是 y_pre
##### 可能会注意到权重参数里有trainable,设置为True的时候是可以权重更迭的,否则对应权重不参与训练
计算loss(tf.keras.losses.xxxx)
# 损失函数也有API loss_function # 这是多分类交叉熵 loss_fn = tf.keras.losses.SparseCategooricalCrossentropy(from_logits=True) # 进行计算 loss = loss_fn(y, y_pre)计算准确度等内置指标(tf.keras.metrics.xxxx)
# 举例选用metric = tf.keras.metrics.AUC() """ 主要使用的方法有三种: 1、metric.update_state(y, y_pre) 2、metric.result() # 获取值 3、metric.reset_state() # 重新开始一个epoch之前进行重置 """动手重新想要的指标(keras.metric.Metric)
class F1Score(keras.metric.Metric):
def __init(self, name='f1_score', dtype='float32', threshold=0.5, **kwargs):
super().__init__(name=name, dtype=dtype, **kwargs)
self.threshold = threshold
self.true_positives = self.add_weight(
name='tp', dtype=dtype, initializer='zeros'
)
self.false_positives = self.add_weight(
name='fp', dtype=dtype, initializer='zeros'
)
self.false_negative = self.add_weight(
name='fn', dtype=dtype, initializer='zeros'
)
def update_state(self, y_true, y_pre, sample_weight=None):
"""先转换成bool进行计算"""
y_pre = tf.math.greater_equal(y_pre, self.threshold)
y_true = tf.cast(y_true, tf.bool)
y_pre = tf.cast(y_pre, tf.bool)
"""再换成float进行求和"""
tp_ = tf.cast(y_true & y_pre, self.dtype)
fp_ = tf.cast(~y_true & y_pre, self.dtype)
fn_ = tf.cast(y_true & ~y_pre, self.dtype)
if sample_weight is not None:
sample_weight = tf.cast(sample_weight, self.dtype)
tp_ *= sample_weight
fp_ *= sample_weight
fn_ *= sample_weigh
"""求和"""
self.true_positives.assign_add(tf.reduce_sum(tp_))
self.false_positives.assign_add(tf.reduce_sum(fp_))
self.false_negatives.assign_add(tf.reduce_sum(fn_))
def result(self):
precision = self.true_positives / (self.true_positives + self.false_positives)
recall = self.true_positives / (self.true_positives + self.false_negatives)
return precision * recall * 2.0 / (precision + recall)
计算梯度(谁对谁求导)
正向求梯度
# keras 其实非常方便的帮助我们做好了这个api
# 以下代码视为:当一个式子建立完成,我们就能够知道他的梯度
with tf.GradientTape() as Tape:
# Tape.watch(x)
# 上方需要注意,当使用的x不是tf.Variable()的时候,需要进行对x的watch
y_pre = linear_layer(x)
loss = loss_fn(y, y_pre)
#dy = Tape.gradient(y, x) # y对x求导
dL = Tape.gradient(loss, Linear_layer.trainable_weights)
反向更新参数
优化器介绍
# 更新的时候都是利用梯度下降调整,步长等内容就和优化器有关 optimizer = tf.keras.optimizers.Adam(learning_rate=1e-3) # 这要在训练前都准备就绪的Gradient decent
# 更新参数 optimizer.apply_gradients(zip(dL, Linear_layer.trainable_weights))多层神经网络
# 堆叠起来就好,使用方式一样,都是同一个父类的
class multi_Layers(keras.layers.Layer):
"""简单堆叠起来"""
def __init__(self):
super(multi_Layers, self).__init__()
self.Dense1 = Linear(32)
self.Dense2 = Linear(32)
self.Dense3 = Linear(10)
def call(self, inputs):
x = self.Dense1(inputs)
x = tf.nn.relu(x)
x = self.Dense2(x)
x = tf.nn.relu(x)
return self.Dense3(x)
add_loss()
# 这个方法会在loss中加上,这个方法只会在最后一次前向传播的时候使用,不会重复堆叠
# 也是使用sublayer
class ActivityRegularization(keras.layers.Layer):
def __init__(self, rate=1e-2):
super(ActivityRegularzation, self).__init__()
self.rate = rate
def call(self, inputs):
self.add_loss(self.rate * tf.reduce_sum(inputs)) # 将维求和
return inputs # 原型返回
Make it fast
@tf.function
def train_on_batch(x, y):
with tf.GradientTape() as tape:
logits = model(x)
loss = loss_fn(y, logits)
gradients = tape.gradient(loss, model.trainable_weights)
optimizer.apply_gradients(zip(gradients, model.trainable_weights))
return loss
定义Dropout层
class Dropout(keras.layers.Layer):
def __init__(self, rate):
super(Dropout, self).__init__()
self.rate = rate
def call(self, inputs, training=None):
if training:
return tf.nn.dropout(inputs, rate=self.rate)
return inputs
自己定义网络在研究中十分有用,而keras中也提供了许多可以用的API,直接使用效率更高一些。
API 大致套路是# 设置层
inputs = tf.keras.Input(shape=(input_dim, ), dtype='float32')
x = Dense(units)(inputs)
# ...(一堆层)
outputs = Dense(units)(x)
# 实例化模型
model = tf.keras.Model(inputs, outputs)
# 模型编译
model.compile(
loss=keras.losses.SparseCategoricalCrossentropy(
from_logits=True),
optimizer=keras.optimizers.Adam(learning_rate=1e-3),
metrics=[keras.metrics.SparseCategoricalAccuracy()],
)
model.fit(dataset, epochs=n_epoch)
自定义model
class CustomModel(keras.Model):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.loss_tracker = keras.metrics.Mean(name="loss")
self.accuracy = keras.metrics.SparseCategoricalAccuracy()
self.loss_fn =
keras.losses.SparseCategoricalCrossentropy(from_logits=True)
self.optimizer = keras.optimizers.Adam(learning_rate=1e-3)
def train_step(self, data):
x, y = data
with tf.GradientTape() as tape:
y_pred = self(x, training=True)
loss = self.loss_fn(y, y_pred)
gradients = tape.gradient(loss, self.trainable_weights)
self.optimizer.apply_gradients(zip(gradients, self.trainable_weights))
self.loss_tracker.update_state(loss)
self.accuracy.update_state(y, y_pred)
return {"loss": self.loss_tracker.result(), "accuracy":
self.accuracy.result()}
@property
def metrics(self):
return [self.loss_tracker, self.accuracy]
- Tips:更多内容在官方API文档中更加详细,有了上面的知识铺垫,看文档就简单多了。



