《TensorFlow深度学习》笔记(二)

反向传播算法

激活函数

  • import numpy as np # 导入 numpy 库 
    def sigmoid(x): # 实现 sigmoid 函数     
        return 1 / (1 + np.exp(-x)) 
     
    def derivative(x):  # sigmoid 导数的计算     
        # sigmoid 函数的表达式由手动推导而得 
        return sigmoid(x)*(1-sigmoid(x))
    
    ##############################################################################
    def derivative(x):  # ReLU 函数的导数     
        d = np.array(x, copy=True)  # 用于保存梯度的张量     
        d[x < 0] = 0  # 元素为负的导数为 0     
        d[x >= 0] = 1  # 元素为正的导数为 1     
        return d 
     
    ##############################################################################
     # 其中 p 为 LeakyReLU 的负半段斜率,为超参数 def derivative(x, p): 
        dx = np.ones_like(x)  # 创建梯度张量,全部初始化为 1     
        dx[x < 0] = p  # 元素为负的导数为 p 
        return dx 
    ##############################################################################
    def sigmoid(x):  # sigmoid 函数实现     return 1 / (1 + np.exp(-x))  
    def tanh(x):  # tanh 函数实现     return 2*sigmoid(2*x) - 1 
    def derivative(x):  # tanh 导数实现 
        return 1-tanh(x)**2 
     
    

Keras 高层接口

常见网络层类

  • # 在 tf.keras.layers 命名空间(下文使用 layers 指代 tf.keras.layers)中提供了大量常见网络层的类,
    # 如全连接层、激活函数层、池化层、卷积层、循环神经网络层等。对于这些网络 层类,只需要在创建时指定
    # 网络层的相关参数,并调用__call__方法即可完成前向计算。在 调用__call__方法时,Keras 会自动调用
    # 每个层的前向传播逻辑,这些逻辑一般实现在类的 call 函数中.
    # 以 Softmax 层为例:
    
    import tensorflow as tf 
    # 导入 keras 模型,不能使用 import keras,它导入的是标准的 Keras 库 
    from tensorflow import keras 
    from tensorflow.keras import layers # 导入常见网络层类 
    
    # 创建 Softmax 层,并调用__call__方法完成前向计算
    x = tf.constant([2.,1.,0.1])  # 创建输入张量 
    layer = layers.Softmax(axis=-1)  # 创建 Softmax 层 
    out = layer(x)  # 调用 softmax 前向计算,输出为 out
    

网络容器

  • 通过 Keras 提供的网络容器 Sequential 将多个 网络层封装成一个大网络模型,只需要调用网络模型的实例一次即可完成数据从第一层到 最末层的顺序传播运算。

  • # 例如,2 层的全连接层加上单独的激活函数层,可以通过 Sequential 容器封装为一个网络。 
    # 导入 Sequential 容器  
    from tensorflow.keras import layers, Sequential 
    network = Sequential([ # 封装为一个网络     
        layers.Dense(3, activation=None),  # 全连接层,此处不使用激活函数 
        layers.ReLU(), # 激活函数层     
        layers.Dense(2, activation=None), # 全连接层,此处不使用激活函数
        layers.ReLU() # 激活函数层 
    ]) 
    x = tf.random.normal([4,3]) 
    out = network(x) # 输入从第一层开始,逐层传播至输出层,并返回输出层的输出 
    
    ##############################################################################
    # Sequential 容器也可以通过 add()方法继续追加新的网络层,实现动态创建网络的功能: 
    layers_num = 2 # 堆叠 2 次 
    network = Sequential([]) # 先创建空的网络容器 
    for _ in range(layers_num): 
        network.add(layers.Dense(3)) # 添加全连接层 
        network.add(layers.ReLU())# 添加激活函数层 
    network.build(input_shape=(4, 4)) # 创建网络参数 
    network.summary()
    # 上述代码通过指定任意的 layers_num 参数即可创建对应层数的网络结构,在完成网络创建 时
    # ,网络层类并没有创建内部权值张量等成员变量,此时通过调用类的 build 方法并指定 输入大
    # 小,即可自动创建所有层的内部张量。通过 summary()函数可以方便打印出网络结 构和参数量
    
    ##############################################################################
    # Sequential 对象的 trainable_variables 和 variables 包含了所有层的待优化张量列表
    # 和全部张量列表
    
     # 打印网络的待优化参数名与 shape 
    for p in network.trainable_variables: 
    print(p.name, p.shape) # 参数名和形状 
    

模型装配、训练与测试

  • 模型装配 :

    • 在 Keras 中,有 2 个比较特殊的类:keras.Model 和 keras.layers.Layer 类。其中 Layer 类是网络层的母类,定义了网络层的一些常见功能,如添加权值、管理权值列表等。 Model 类是网络的母类,除了具有 Layer 类的功能,还添加了保存模型、加载模型、训练 与测试模型等便捷功能。Sequential 也是 Model 的子类,因此具有 Model 类的所有功能。
  • # MNIST 手写数字图片识
    # 创建 5 层的全连接网络 
    network = Sequential([layers.Dense(256, activation='relu'),                      
                          layers.Dense(128, activation='relu'),   
                          layers.Dense(64, activation='relu'),   
     					layers.Dense(32, activation='relu'),      
                          layers.Dense(10)]) 
    network.build(input_shape=(4, 28*28)) 
    network.summary() 
    
    #  创建网络后,正常的流程是循环迭代数据集多个 Epoch,每次按批产生训练数据、前向计算,
    # 然后通过损失函数计算误差值,并反向传播自动计算梯度、更新网络参数。这一 部分 逻辑由
    # 于非常通用,在 Keras 中提供了 compile()和 fit()函数方便实现上述逻辑。首先通过 
    # compile 函数指定网络使用的优化器对象、损失函数类型,评价指标等设定,这一步称为装配。
    # 导入优化器,损失函数模块 
      from tensorflow.keras import optimizers,losses  
    # 模型装配 
    # 采用 Adam 优化器,学习率为 0.01;采用交叉熵损失函数包含Softmax 
    network.compile(optimizer=optimizers.Adam(lr=0.01),        
    loss=losses.CategoricalCrossentropy(from_logits=True), 
            metrics=['accuracy'] # 设置测量指标为准确率 
    ) 
    
  • 模型训练

    • # 模型装配完成后,即可通过 fit()函数送入待训练的数据集和验证用的数据集,这一步 称为模型训练。
      # 指定训练集为 train_db,验证集为 val_db,训练 5 个 epochs,每 2 个 epoch 验证一次 
      # 返回训练轨迹信息保存在 history 对象中 
      history = network.fit(train_db, epochs=5, validation_data=val_db, validation_freq=2) 
      # 运行上述代码即可实现网络的训练与验证的功能,fit 函数会返回训练过程的数据记录 history,
      # 其中 history.history 为字典对象,包含了训练过程中的 loss、测量指标等记录项, 我们可以
      # 直接查看这些训练数据
      history.history # 打印训练记录
      
      
  • 模型测试

    • Model 基类除了可以便捷地完成网络的装配与训练、验证,还可以非常方便的预测和 测试。

    • # 通过 Model.predict(x)方法即可完成模型的预测
      # 加载一个 batch 的测试数据 
      x,y = next(iter(db_test)) print('predict x:', x.shape) # 打印当前 batch 的形状 
      out = network.predict(x) # 模型预测,预测结果保存在 out 中 
      print(out)
      

模型保存与加载

  • 张量方式

  • # Model.save_weights(path)方法即可将当前的 网络参数保存到 path 文件上,代码如下: 
    network.save_weights('weights.ckpt') # 保存模型的所有张量数据 
    # 上述代码将 network 模型保存到 weights.ckpt 文件上。
    
    # 例子:
    # 保存模型参数到文件上 
    network.save_weights('weights.ckpt') print('saved weights.') 
    del network # 删除网络对象 
    # 重新创建相同的网络结构 
    network = Sequential([layers.Dense(256, activation='relu'),                     
                          layers.Dense(128, activation='relu'),                      
      					layers.Dense(64, activation='relu'),                           
       					layers.Dense(32, activation='relu'),                      
       					layers.Dense(10)])
    network.compile(optimizer=optimizers.Adam(lr=0.01),         						loss=tf.losses.CategoricalCrossentropy(from_logits=True),        
            metrics=['accuracy'])  
    # 从参数文件中读取数据并写入当前网络 
    network.load_weights('weights.ckpt') 
    print('loaded weights!') 
    
    
  • 网络方式

    • 通过 Model.save(path) 函数将模型的结构及其参数保存到path路径
    • keras.models.load_model(path) 函数将模型的结构及其参数恢复
  • SavedModel 方式

  • # 保存模型结构与模型参数到文件 
    tf.saved_model.save(network, 'model-savedmodel') 
    print('saving savedmodel.') 
    del network # 删除网络对象
    print('load savedmodel from file.') # 从文件恢复网络结构与网络参数 
    network =  tf.saved_model.load('model-savedmodel') # 准确率计量器  
    acc_meter = metrics.CategoricalAccuracy()  
    for x,y in ds_val:  # 遍历测试集
        pred = network(x) # 前向计算     
        acc_meter.update_state(y_true=y, y_pred=pred) # 更新准确率统计
        # 打印准确率 
    print("Test Accuracy:%f" % acc_meter.result())
    

自定义网络层

  • # 通过 Sequential 容器方便地封装成一个网络模 型
    network = Sequential([
    MyDense(784, 256), # 使用自定义的层      
    MyDense(256, 128),                      
    MyDense(128, 64),                     
    MyDense(64, 32),                     
    MyDense(32, 10)])
    network.build(input_shape=(None, 28*28)) 
    network.summary() 
    
    # 来创建自定义网络类
    class MyModel(keras.Model): 
        # 自定义网络类,继承自 Model 基类     
        def __init__(self):         
            super(MyModel, self).__init__() 
            # 完成网络内需要的网络层的创建工作         
            self.fc1 = MyDense(28*28, 256)         
            self.fc2 = MyDense(256, 128)         
            self.fc3 = MyDense(128, 64) 
            self.fc4 = MyDense(64, 32) 
            self.fc5 = MyDense(32, 10) 
            
     # 实现自定义网络的前向运算逻
     def call(self, inputs, training=None): 
            # 自定义前向运算逻辑         
            x = self.fc1(inputs)          
            x = self.fc2(x)          
            x = self.fc3(x)          
            x = self.fc4(x)          
            x = self.fc5(x)  
            return x 
    
    

测量工具

  • Keras 的测量工具的使用方法一般有 4 个主要步骤:新建测量器,写入数据,读取统 计数据和清零测量器。

  • # 统计误差值
    # 新建测量器 ,在 keras.metrics 模块中,提供了较多的常用测量器类,如统计平均值的 Mean 类,
    # 统计准确率的 Accuracy 类,统计余弦相似度的 CosineSimilarity 类等
    # 新建平均测量器,适合 Loss 数据 
    loss_meter = metrics.Mean() 
    
    # 写入数据 
    # 记录采样的数据,通过 float()函数将张量转换为普通数值 
    loss_meter.update_state(float(loss)) 
    
    # 读取统计信息 
    # 打印统计期间的平均 loss 
    print(step, 'loss:', loss_meter.result()) 
    
    #  清除状态 
     if step % 100 == 0: 
            # 打印统计的平均 loss         
            print(step, 'loss:', loss_meter.result())  
            loss_meter.reset_states() # 打印完后,清零测量器 
            
     ####################################################################
    
    # 统计准确率
    acc_meter = metrics.Accuracy() # 创建准确率测量器 
    
    # 。需要注意的是,Accuracy 类的 update_state 函数的参数为预测值和真实值,而不是
    # 当前 Batch 的准确率。
     # [b, 784] => [b, 10],网络输出值             
     out = network(x)  
     # [b, 10] => [b],经过 argmax 后计算预测值             
     pred = tf.argmax(out, axis=1)              
     pred = tf.cast(pred, dtype=tf.int32) 
     # 根据预测值与真实值写入测量器 
     acc_meter.update_state(y, pred)
     # 读取统计结果        
     print(step, 'Evaluate Acc:', 
     acc_meter.result().numpy()) 
     acc_meter.reset_states() # 清零测量器 
    
    

过拟合

  • Early stopping 正则化 Dropout
  • 数据增强( 旋转 , 翻转 ,裁剪 )
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值