zoukankan      html  css  js  c++  java
  • tensorfolw学习笔记——张量、微分、自定义训练、keras

    1张量

    张量可以使用GPU加速,可以自动将python内置数据类型转换为张量。张量有形状和数据类型。张量与numpy主要区别为:1张量可以用GPU加速2张量不可变。

    Tensors和Numpy ndarrays可以自动相互转换。Tensors使用.numpy()方法可以显示转换为ndarray。这种转换让Tensors和ndarray共享了底层内存。Tensors可能在GPU内存可是Numpy总是在cpu内存,转换涉及从GPU到主机内存的复制。

    import numpy as np
    
    ndarray = np.ones([3, 3])
    
    print("TensorFlow operations convert numpy arrays to Tensors automatically")
    tensor = tf.multiply(ndarray, 42)
    print(tensor)
    
    
    print("And NumPy operations convert Tensors to numpy arrays automatically")
    print(np.add(tensor, 1))
    
    print("The .numpy() method explicitly converts a Tensor to a numpy array")
    print(tensor.numpy())
    

      

    TensorFlow operations convert numpy arrays to Tensors automatically
    tf.Tensor(
    [[42. 42. 42.]
     [42. 42. 42.]
     [42. 42. 42.]], shape=(3, 3), dtype=float64)
    And NumPy operations convert Tensors to numpy arrays automatically
    [[43. 43. 43.]
     [43. 43. 43.]
     [43. 43. 43.]]
    The .numpy() method explicitly converts a Tensor to a numpy array
    [[42. 42. 42.]
     [42. 42. 42.]
     [42. 42. 42.]]
    

    Tensorflow自动决定是否使用GPU来加速运算。Tensor.device提供了设备信息。可以显示设置执行计算的设备。

    Dateset:

    tf.data.Dataset将数据喂给算法,迭代简单。Dataset.from_tensors,Dataset.from_tensor_slices,TextLineDataset,TFRecordDataset可以创建dataset。map,batch,shuffle用来对dataset转换处理。dataset可以直接用于迭代(如for循环)。

    ds_tensors = tf.data.Dataset.from_tensor_slices([1, 2, 3, 4, 5, 6])
    
    # Create a CSV file
    import tempfile
    _, filename = tempfile.mkstemp()
    
    with open(filename, 'w') as f:
      f.write("""Line 1
    Line 2
    Line 3
      """)
    
    ds_file = tf.data.TextLineDataset(filename)
    
    ds_tensors = ds_tensors.map(tf.square).shuffle(2).batch(2)
    
    ds_file = ds_file.batch(2)
    
    
    print('Elements of ds_tensors:')
    for x in ds_tensors:
      print(x)
    
    print('
    Elements in ds_file:')
    for x in ds_file:
      print(x)
    
    
    Elements of ds_tensors:
    tf.Tensor([4 1], shape=(2,), dtype=int32)
    tf.Tensor([ 9 16], shape=(2,), dtype=int32)
    tf.Tensor([25 36], shape=(2,), dtype=int32)
    
    Elements in ds_file:
    tf.Tensor([b'Line 1' b'Line 2'], shape=(2,), dtype=string)
    tf.Tensor([b'Line 3' b'  '], shape=(2,), dtype=string)

     2自动微分

    利用张量类型在描述清楚变量之间关系,TensorFlow自动计算变量的微分和梯度。tf.GradientTape用来计算自动微分。

    x = tf.ones((2, 2))
    
    with tf.GradientTape() as t:
      t.watch(x)
      y = tf.reduce_sum(x)
      z = tf.multiply(y, y)
    
    # Derivative of z with respect to the original input tensor x
    dz_dx = t.gradient(z, x)
    for i in [0, 1]:
      for j in [0, 1]:
        assert dz_dx[i][j].numpy() == 8.0

    也可对中间变量进行微分:

    x = tf.ones((2, 2))
    
    with tf.GradientTape() as t:
      t.watch(x)
      y = tf.reduce_sum(x)
      z = tf.multiply(y, y)
    
    # Use the tape to compute the derivative of z with respect to the
    # intermediate value y.
    dz_dy = t.gradient(z, y)
    assert dz_dy.numpy() == 8.0

    默认只要调用gradient方法,GradientTape持有的资源就会被释放。为了对多个变量进行微分,需要进行tf.GradientTape(persistent=True)设置。如:

    x = tf.constant(3.0)
    with tf.GradientTape(persistent=True) as t:
      t.watch(x)
      y = x * x
      z = y * y
    dz_dx = t.gradient(z, x)  # 108.0 (4*x^3 at x = 3)
    dy_dx = t.gradient(y, x)  # 6.0
    del t  # Drop the reference to the tape

    可以对导数再进行求导(二阶导数):

    x = tf.Variable(1.0)  # Create a Tensorflow variable initialized to 1.0
    
    with tf.GradientTape() as t:
      with tf.GradientTape() as t2:
        y = x * x * x
      # Compute the gradient inside the 't' context manager
      # which means the gradient computation is differentiable as well.
      dy_dx = t2.gradient(y, x)
    d2y_dx2 = t.gradient(dy_dx, x)
    
    assert dy_dx.numpy() == 3.0
    assert d2y_dx2.numpy() == 6.0

    3自定义训练

    线性拟合实例。

    class Model(object):
      def __init__(self):
        # Initialize variable to (5.0, 0.0)
        # In practice, these should be initialized to random values.
        self.W = tf.Variable(5.0)
        self.b = tf.Variable(0.0)
    
      def __call__(self, x):
        return self.W * x + self.b
    
    model = Model()
    
    assert model(3.0).numpy() == 15.0
    
    def loss(predicted_y, desired_y):  #定义损失函数
      return tf.reduce_mean(tf.square(predicted_y - desired_y))
    
    TRUE_W = 3.0
    TRUE_b = 2.0
    NUM_EXAMPLES = 1000
    
    inputs  = tf.random_normal(shape=[NUM_EXAMPLES])
    noise   = tf.random_normal(shape=[NUM_EXAMPLES])
    outputs = inputs * TRUE_W + TRUE_b + noise #有噪声的y值
    
    import matplotlib.pyplot as plt  #画出预测值和真实值图
    
    plt.scatter(inputs, outputs, c='b')
    plt.scatter(inputs, model(inputs), c='r')
    plt.show()
    
    print('Current loss: '),
    print(loss(model(inputs), outputs).numpy())

    def train(model, inputs, outputs, learning_rate):  #更新权重
      with tf.GradientTape() as t:
        current_loss = loss(model(inputs), outputs)
      dW, db = t.gradient(current_loss, [model.W, model.b])
      model.W.assign_sub(learning_rate * dW)
      model.b.assign_sub(learning_rate * db)

    model = Model()

    # Collect the history of W-values and b-values to plot later
    Ws, bs = [], []
    epochs = range(10)
    for epoch in epochs: #迭代10次
      Ws.append(model.W.numpy())
      bs.append(model.b.numpy())
      current_loss = loss(model(inputs), outputs)

      train(model, inputs, outputs, learning_rate=0.1)
      print('Epoch %2d: W=%1.2f b=%1.2f, loss=%2.5f' %
            (epoch, Ws[-1], bs[-1], current_loss))

    # Let's plot it all
    plt.plot(epochs, Ws, 'r',
             epochs, bs, 'b')
    plt.plot([TRUE_W] * len(epochs), 'r--',
             [TRUE_b] * len(epochs), 'b--')
    plt.legend(['W', 'b', 'true W', 'true_b'])
    plt.show()

    #随着迭代次数增加,loss越来越少
    Epoch  0: W=5.00 b=0.00, loss=9.36370
    Epoch  1: W=4.59 b=0.42, loss=6.28548
    Epoch  2: W=4.26 b=0.75, loss=4.34777
    Epoch  3: W=4.00 b=1.01, loss=3.12800
    Epoch  4: W=3.80 b=1.22, loss=2.36017
    Epoch  5: W=3.64 b=1.39, loss=1.87683
    Epoch  6: W=3.51 b=1.52, loss=1.57257
    Epoch  7: W=3.40 b=1.62, loss=1.38104
    Epoch  8: W=3.32 b=1.70, loss=1.26047
    Epoch  9: W=3.26 b=1.77, loss=1.18457


     

    4keras

    Keras是一种高级抽象的API。

    # In the tf.keras.layers package, layers are objects. To construct a layer,
    # simply construct the object. Most layers take as a first argument the number
    # of output dimensions / channels.
    layer = tf.keras.layers.Dense(100)
    # The number of input dimensions is often unnecessary, as it can be inferred
    # the first time the layer is used, but it can be provided if you want to 输入可选
    # specify it manually, which is useful in some complex models.
    layer = tf.keras.layers.Dense(10, input_shape=(None, 5))

    层的类型包括Dense(全连接层),Conv2D,LSTM,BatchNormalization,Dropout。

    # To use a layer, simply call it.
    layer(tf.zeros([10, 5]))  #提供输入,开始计算
    
    <tf.Tensor: id=29, shape=(10, 10), dtype=float32, numpy=
    array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
           [0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]], dtype=float32)>
    
    # Layers have many useful methods. For example, you can inspect all variables
    # in a layer using `layer.variables` and trainable variables using
    # `layer.trainable_variables`. In this case a fully-connected layer
    # will have variables for weights and biases.
    layer.variables  #权重包括w和b
    
    [<tf.Variable 'dense_1/kernel:0' shape=(5, 10) dtype=float32, numpy=
     array([[ 0.24547583, -0.18174013, -0.517627  , -0.28625917,  0.46390074,
             -0.11792481,  0.25204027, -0.10177726, -0.6321482 ,  0.11025655],
            [-0.04801774,  0.05520332, -0.61134326, -0.380753  , -0.20825565,
              0.44676226,  0.34310788, -0.18177858, -0.0399543 , -0.6257955 ],
            [-0.09570092,  0.2136836 ,  0.11427677,  0.45249623,  0.02414119,
              0.2739644 , -0.5701976 , -0.28433737,  0.1094352 , -0.26321137],
            [ 0.6225632 ,  0.56247157,  0.14319342, -0.27484533,  0.06545639,
             -0.14055312,  0.02605182, -0.17947513, -0.43184835, -0.13298517],
            [ 0.21471226, -0.34008306,  0.13555825, -0.20253879, -0.14976257,
              0.24820238,  0.4052704 , -0.42966282,  0.46730322,  0.5801386 ]],
           dtype=float32)>,
     <tf.Variable 'dense_1/bias:0' shape=(10,) dtype=float32, numpy=array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)>]  

    class MyDenseLayer(tf.keras.layers.Layer):  #封装
      def __init__(self, num_outputs):
        super(MyDenseLayer, self).__init__() #调用基类构造函数
        self.num_outputs = num_outputs

      def build(self, input_shape):
        self.kernel = self.add_variable("kernel",
                                        shape=[int(input_shape[-1]),
                                               self.num_outputs])

      def call(self, input):
        return tf.matmul(input, self.kernel)

    layer = MyDenseLayer(10)
    print(layer(tf.zeros([10, 5])))
    print(layer.trainable_variables)


    tf.Tensor(
    [[0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.]], shape=(10, 10), dtype=float32)
    [<tf.Variable 'my_dense_layer/kernel:0' shape=(5, 10) dtype=float32, numpy=
    array([[ 0.40808827,  0.31189376, -0.6253119 , -0.5369232 , -0.6137004 ,
            -0.5453413 , -0.27606115, -0.60044795,  0.42764622,  0.25756943],
           [ 0.11746502,  0.40135378,  0.27446055,  0.12815869,  0.19679207,
             0.118303  , -0.5602601 , -0.3910997 , -0.50229526, -0.4392987 ],
           [-0.11431473,  0.30567902, -0.42285785,  0.41714746,  0.54528743,
             0.20401049, -0.0829075 ,  0.4709614 , -0.60372585, -0.45935804],
           [-0.51994437, -0.40799683,  0.306705  ,  0.588075  ,  0.12873381,
            -0.12829626,  0.03449196,  0.5080891 , -0.5090939 ,  0.1574735 ],
           [-0.30528757, -0.3296884 ,  0.168805  ,  0.40543085,  0.46509403,
            -0.52575713, -0.181254  , -0.24681184, -0.37497327, -0.37618726]],
          dtype=float32)>]
     

    将tf.keras.Model 封装,自定义类

    class ResnetIdentityBlock(tf.keras.Model):
      def __init__(self, kernel_size, filters):
        super(ResnetIdentityBlock, self).__init__(name='')
        filters1, filters2, filters3 = filters
    
        self.conv2a = tf.keras.layers.Conv2D(filters1, (1, 1))
        self.bn2a = tf.keras.layers.BatchNormalization()
    
        self.conv2b = tf.keras.layers.Conv2D(filters2, kernel_size, padding='same')
        self.bn2b = tf.keras.layers.BatchNormalization()
    
        self.conv2c = tf.keras.layers.Conv2D(filters3, (1, 1))
        self.bn2c = tf.keras.layers.BatchNormalization()
    
      def call(self, input_tensor, training=False):  #重载调用运算符
        x = self.conv2a(input_tensor)
        x = self.bn2a(x, training=training)
        x = tf.nn.relu(x)
    
        x = self.conv2b(x)
        x = self.bn2b(x, training=training)
        x = tf.nn.relu(x)
    
        x = self.conv2c(x)
        x = self.bn2c(x, training=training)
    
        x += input_tensor
        return tf.nn.relu(x)
    
    
    block = ResnetIdentityBlock(1, [1, 2, 3])
    print(block(tf.zeros([1, 2, 3, 3])))
    print([x.name for x in block.trainable_variables])
    
    
    tf.Tensor(
    [[[[0. 0. 0.]
       [0. 0. 0.]
       [0. 0. 0.]]
    
      [[0. 0. 0.]
       [0. 0. 0.]
       [0. 0. 0.]]]], shape=(1, 2, 3, 3), dtype=float32)
    ['resnet_identity_block/conv2d/kernel:0', 'resnet_identity_block/conv2d/bias:0', 'resnet_identity_block/batch_normalization/gamma:0', 'resnet_identity_block/batch_normalization/beta:0', 'resnet_identity_block/conv2d_1/kernel:0', 'resnet_identity_block/conv2d_1/bias:0', 'resnet_identity_block/batch_normalization_1/gamma:0', 'resnet_identity_block/batch_normalization_1/beta:0', 'resnet_identity_block/conv2d_2/kernel:0', 'resnet_identity_block/conv2d_2/bias:0', 'resnet_identity_block/batch_normalization_2/gamma:0', 'resnet_identity_block/batch_normalization_2/beta:0']

    更常用的是tf.keras.Sequential函数,将每层逐一写出:

     my_seq = tf.keras.Sequential([tf.keras.layers.Conv2D(1, (1, 1)),
                                   tf.keras.layers.BatchNormalization(),
                                   tf.keras.layers.Conv2D(2, 1,
                                                          padding='same'),
                                   tf.keras.layers.BatchNormalization(),
                                   tf.keras.layers.Conv2D(3, (1, 1)),
                                   tf.keras.layers.BatchNormalization()])
    my_seq(tf.zeros([1, 2, 3, 3]))
    
    <tf.Tensor: id=514, shape=(1, 2, 3, 3), dtype=float32, numpy=
    array([[[[0., 0., 0.],
             [0., 0., 0.],
             [0., 0., 0.]],
    
            [[0., 0., 0.],
             [0., 0., 0.],
             [0., 0., 0.]]]], dtype=float32)>

    6按品种对鸢尾花进行分类

  • 相关阅读:
    php.ini常用设置
    php 登录时用户名与密码验证器
    php Array操作函数
    php 注册时输入信息验证器
    php从数组中随机抽取一些元素
    php 字符串操作函数
    php类的注册与自动加载
    php 跑龙套功能——页面跳转
    围棋界的后阿拉法狗时代——“云养狗”
    云养狗的启发——区块链的新应用可能性乱想
  • 原文地址:https://www.cnblogs.com/biwangwang/p/11267173.html
Copyright © 2011-2022 走看看