Skip to content

D2L-CH5-Deep Learning Computation


因為TF2版本實做舊版的電子書內容,因此以下章節編排用Ch4命名.

https://trickygo.github.io/Dive-into-DL-TensorFlow2.0/#/


Deep Learning Computation

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
import numpy as np
import tensorflow as tf
print(tf.__version__)

assert int(tf.__version__[0]) == 2
2.0.0
print(tf.test.is_gpu_available())
True

4.1 模型构造

4.1.1 build model from block

class MLP(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.flatten = tf.keras.layers.Flatten()    # Flatten层将除第一维(batch_size)以外的维度展平
        self.dense1 = tf.keras.layers.Dense(units=256, activation=tf.nn.relu)
        self.dense2 = tf.keras.layers.Dense(units=10)

    def call(self, inputs):
        x = self.flatten(inputs)
        print(x.shape)
        x = self.dense1(x)
        print(x.shape)
        output = self.dense2(x)
        return output
X = tf.random.uniform((2,20))
net = MLP()
net(X)
(2, 20)
(2, 256)





<tf.Tensor: id=62, shape=(2, 10), dtype=float32, numpy=
array([[ 0.84096867,  0.10880844, -0.19298258,  0.09622616, -0.3129447 ,
         0.05816094,  0.01181953, -0.36879984,  0.07114434, -0.23152365],
       [ 0.33144152,  0.04583085, -0.27655935,  0.04085173, -0.10101503,
         0.00194229,  0.03036133, -0.2423382 ,  0.05986395,  0.00838697]],
      dtype=float32)>

4.1.2 Sequential

model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(256, activation=tf.nn.relu),
    tf.keras.layers.Dense(10),
])

model(X)
<tf.Tensor: id=117, shape=(2, 10), dtype=float32, numpy=
array([[-0.09959396, -0.45667994, -0.31671545,  0.38400424,  0.29135102,
        -0.1833095 , -0.09414536, -0.53436816, -0.00413986, -0.12974967],
       [-0.14006008, -0.41170198, -0.04489394,  0.24267752,  0.22950622,
        -0.03381499,  0.03787727, -0.32568848,  0.04253128, -0.27896702]],
      dtype=float32)>

4.1.3 build complex model

class FancyMLP(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.flatten = tf.keras.layers.Flatten()
        self.rand_weight = tf.constant(tf.random.uniform((20,20)))
        self.dense = tf.keras.layers.Dense(units=20, activation=tf.nn.relu)

    def call(self, inputs):
        x = self.flatten(inputs)
        print(x.shape)
        x = tf.nn.relu(tf.matmul(x, self.rand_weight) + 1)
        print(x.shape)
        x = self.dense(x)
        print(x.shape)
        while tf.norm(x) > 1:
            x /= 2
        if tf.norm(x) < 0.8:
            x *= 10
        print(x.shape)
        return tf.reduce_sum(x)
net = FancyMLP()
net(X)
(2, 20)
(2, 20)
(2, 20)
(2, 20)





<tf.Tensor: id=229, shape=(), dtype=float32, numpy=22.884422>
class NestMLP(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.net = tf.keras.Sequential()
        self.net.add(tf.keras.layers.Flatten())
        self.net.add(tf.keras.layers.Dense(64, activation=tf.nn.relu))
        self.net.add(tf.keras.layers.Dense(32, activation=tf.nn.relu))
        self.dense = tf.keras.layers.Dense(units=16, activation=tf.nn.relu)

    def call(self, inputs):
        return self.dense(self.net(inputs))

net = tf.keras.Sequential()
net.add(NestMLP())
net.add(tf.keras.layers.Dense(20))
net.add(FancyMLP())

net(X)
(2, 20)
(2, 20)
(2, 20)
(2, 20)





<tf.Tensor: id=421, shape=(), dtype=float32, numpy=3.6778188>

4.2 模型参数的访问、初始化和共享

net = tf.keras.models.Sequential()
net.add(tf.keras.layers.Flatten())
net.add(tf.keras.layers.Dense(256,activation=tf.nn.relu))
net.add(tf.keras.layers.Dense(10))

X = tf.random.uniform((2,20))
Y = net(X)
Y
<tf.Tensor: id=483, shape=(2, 10), dtype=float32, numpy=
array([[-0.09879929,  0.2812114 , -0.06708632, -0.36011535,  0.2831914 ,
         0.26097357, -0.00985743, -0.21124828, -0.1133031 , -0.02720478],
       [ 0.07838846,  0.20481616,  0.05093011, -0.25614202,  0.09847108,
         0.37754467, -0.07446901, -0.24943468, -0.13108218,  0.24933031]],
      dtype=float32)>

4.2.1 access model parameters

net.weights[0]
type(net.weights[0])
<tf.Variable 'sequential_3/dense_10/kernel:0' shape=(20, 256) dtype=float32, numpy=
array([[-0.07033821,  0.04328914, -0.02081853, ..., -0.09415226,
        -0.13597511,  0.0630572 ],
       [ 0.06236269, -0.12134855,  0.09827602, ...,  0.1120435 ,
         0.00854841,  0.05130161],
       [-0.0358071 , -0.12622362,  0.05006796, ..., -0.09388144,
         0.03304952,  0.11275896],
       ...,
       [ 0.10420921, -0.1144833 ,  0.02463526, ...,  0.08800317,
         0.0538664 , -0.14500125],
       [ 0.10294706,  0.03746136,  0.04467554, ..., -0.05025613,
        -0.01331051,  0.05202538],
       [-0.0107531 ,  0.10216615,  0.04870357, ...,  0.06093717,
        -0.08508429, -0.05277579]], dtype=float32)>






tensorflow.python.ops.resource_variable_ops.ResourceVariable

4.2.2 initialize params

class Linear(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.d1 = tf.keras.layers.Dense(
            units=10,
            activation=None,
            kernel_initializer=tf.zeros_initializer(),
            bias_initializer=tf.zeros_initializer()
        )
        self.d2 = tf.keras.layers.Dense(
            units=1,
            activation=None,
            kernel_initializer=tf.ones_initializer(),
            bias_initializer=tf.ones_initializer()
        )

    def call(self, input):
        output = self.d1(input)
        output = self.d2(output)
        return output


net = Linear()
net(X)
net.get_weights()
<tf.Tensor: id=529, shape=(2, 1), dtype=float32, numpy=
array([[1.],
       [1.]], dtype=float32)>






[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.],
        [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),
 array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32),
 array([[1.],
        [1.],
        [1.],
        [1.],
        [1.],
        [1.],
        [1.],
        [1.],
        [1.],
        [1.]], dtype=float32),
 array([1.], dtype=float32)]

4.2.3 define initializer

def my_init():
    return tf.keras.initializers.Ones()


model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(64, kernel_initializer=my_init()))

Y = model(X)
model.weights[0]
<tf.Variable 'sequential_4/dense_14/kernel:0' shape=(20, 64) dtype=float32, numpy=
array([[1., 1., 1., ..., 1., 1., 1.],
       [1., 1., 1., ..., 1., 1., 1.],
       [1., 1., 1., ..., 1., 1., 1.],
       ...,
       [1., 1., 1., ..., 1., 1., 1.],
       [1., 1., 1., ..., 1., 1., 1.],
       [1., 1., 1., ..., 1., 1., 1.]], dtype=float32)>

4.4 自定义层

X = tf.random.uniform((2,20))

4.4.1 custom layer without parameters

# 自定义了一个将输入减掉均值后输出的层

class CenteredLayer(tf.keras.layers.Layer):
    def __init__(self):
        super().__init__()

    def call(self, inputs):
        return inputs - tf.reduce_mean(inputs)


layer = CenteredLayer()
layer(np.array([1,2,3,4,5]))
<tf.Tensor: id=572, shape=(5,), dtype=int64, numpy=array([-2, -1,  0,  1,  2])>
net = tf.keras.models.Sequential()
net.add(tf.keras.layers.Flatten())
net.add(tf.keras.layers.Dense(20))
net.add(CenteredLayer())

Y = net(X)
Y
<tf.Tensor: id=603, shape=(2, 20), dtype=float32, numpy=
array([[-0.63349915, -0.40265122,  1.2623289 , -1.1872962 , -0.01902312,
        -0.8613274 ,  1.0604925 ,  0.14521688,  1.3011982 , -0.5348058 ,
         0.98438555, -0.4622898 , -0.27724132,  1.0449705 , -0.9285989 ,
         0.4628783 ,  0.52180976, -1.5547564 , -0.4817221 , -0.12175441],
       [-0.31887224,  0.17624336,  0.46425617, -0.7229486 , -0.04514135,
        -0.38868698,  1.1368203 ,  0.03690258,  1.3245962 , -0.12987542,
         0.5836614 , -0.4206456 , -0.849625  ,  0.22945827, -0.6439618 ,
         0.31676728,  0.9253774 , -1.1312481 , -0.39756632,  0.5361735 ]],
      dtype=float32)>
Y.shape
tf.reduce_mean(Y)
Y.numpy().mean()
TensorShape([2, 20])






<tf.Tensor: id=605, shape=(), dtype=float32, numpy=-2.9802323e-09>






5.9604646e-09

4.4.2 custom layer with parameters

class myDense(tf.keras.layers.Layer):
    def __init__(self, units):
        super().__init__()
        self.units = units

    def build(self, input_shape):     # 这里 input_shape 是第一次运行call()时参数inputs的形状
        self.w = self.add_weight(name='w',
            shape=[input_shape[-1], self.units], initializer=tf.random_normal_initializer())
        self.b = self.add_weight(name='b',
            shape=[self.units], initializer=tf.zeros_initializer())

    def call(self, inputs):
        y_pred = tf.matmul(inputs, self.w) + self.b
        return y_pred


dense = myDense(3)
dense(X)
dense.get_weights()
<tf.Tensor: id=630, shape=(2, 3), dtype=float32, numpy=
array([[-0.12120296, -0.0113711 ,  0.14779961],
       [-0.06124324, -0.23015328,  0.15629828]], dtype=float32)>






[array([[ 0.05555374,  0.02348969,  0.0034632 ],
        [-0.03911855, -0.07329117, -0.02120967],
        [-0.0106332 ,  0.01186991, -0.08006126],
        [-0.01038213,  0.01291886, -0.09378239],
        [ 0.01282662, -0.06754901,  0.09265347],
        [ 0.03958872, -0.12498979,  0.09561845],
        [-0.00686976, -0.01925179,  0.03493042],
        [-0.08048819,  0.07349076, -0.02351638],
        [ 0.05533304, -0.07750282, -0.05470523],
        [-0.12362194, -0.00875609,  0.01370332],
        [ 0.02532404, -0.00088338,  0.02777285],
        [ 0.04859733, -0.02423888, -0.02878525],
        [ 0.01547945,  0.05682674,  0.08475035],
        [-0.05850073,  0.09705635, -0.04129069],
        [-0.09561963,  0.04900615,  0.01821384],
        [-0.01083881, -0.0033182 ,  0.05659602],
        [-0.00601833,  0.00671248,  0.03593432],
        [-0.02513886,  0.02864583,  0.08744691],
        [ 0.04603861, -0.06716666,  0.15384746],
        [ 0.07991496, -0.06417349, -0.06345452]], dtype=float32),
 array([0., 0., 0.], dtype=float32)]

4.5 读取和存储

4.5.1 load and save NDarray

x = tf.ones(3)
x
<tf.Tensor: id=637, shape=(3,), dtype=float32, numpy=array([1., 1., 1.], dtype=float32)>
np.save('x.npy', x)
x2 = np.load('x.npy')
x2
array([1., 1., 1.], dtype=float32)
y = tf.zeros(4)
np.save('xy.npy',[x, y])
x2, y2 = np.load('xy.npy', allow_pickle=True)
(x2, y2)
(<tf.Tensor: id=641, shape=(3,), dtype=float32, numpy=array([1., 1., 1.], dtype=float32)>,
 <tf.Tensor: id=642, shape=(4,), dtype=float32, numpy=array([0., 0., 0., 0.], dtype=float32)>)
mydict = {'x': x, 'y': y}
np.save('mydict.npy', mydict)
mydict2 = np.load('mydict.npy', allow_pickle=True)
mydict2
array({'x': <tf.Tensor: id=643, shape=(3,), dtype=float32, numpy=array([1., 1., 1.], dtype=float32)>, 'y': <tf.Tensor: id=644, shape=(4,), dtype=float32, numpy=array([0., 0., 0., 0.], dtype=float32)>},
      dtype=object)

4.5.2 load and save model parameters

X = tf.random.normal((2,20))
X
<tf.Tensor: id=650, shape=(2, 20), dtype=float32, numpy=
array([[-0.70839405,  0.64460796, -1.4520555 ,  0.2437724 ,  1.2570765 ,
        -1.6705031 , -0.31433955,  1.8855785 , -1.133219  , -0.21667722,
        -1.4931314 , -1.3752788 , -1.7839235 , -0.14742793, -0.49592182,
         1.0912119 ,  1.3237706 , -0.15733577, -0.6948644 , -0.09535565],
       [-0.29845145, -1.0061126 ,  0.55780685, -0.8957967 , -0.20540899,
        -1.2849039 ,  1.3647797 , -1.1219321 ,  0.50872946,  0.48485067,
        -0.8191421 ,  0.4611657 , -1.9845624 ,  0.284558  , -0.60567355,
        -0.06300711,  0.6070405 , -0.8394772 , -0.9673258 , -0.37527218]],
      dtype=float32)>
class MLP(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.flatten = tf.keras.layers.Flatten()    # Flatten层将除第一维(batch_size)以外的维度展平
        self.dense1 = tf.keras.layers.Dense(units=256, activation=tf.nn.relu)
        self.dense2 = tf.keras.layers.Dense(units=10)

    def call(self, inputs):
        x = self.flatten(inputs)
        x = self.dense1(x)
        output = self.dense2(x)
        return output

net = MLP()
Y = net(X)
Y
<tf.Tensor: id=705, shape=(2, 10), dtype=float32, numpy=
array([[-0.7419181 ,  0.09955069,  0.7849864 ,  0.6915925 , -0.28200203,
        -0.1542021 ,  0.12158332, -0.96637523, -0.2665258 , -0.98705816],
       [-0.2809674 , -0.01123159,  0.3605952 , -0.12920402,  0.68370396,
        -0.18064019,  0.09563297, -0.2262938 , -0.28119707, -0.18144041]],
      dtype=float32)>
net.save_weights("4.5saved_model.h5")
net2 = MLP()
net2(X)
net2.load_weights("4.5saved_model.h5")
Y2 = net2(X)
Y2 == Y
<tf.Tensor: id=768, shape=(2, 10), dtype=float32, numpy=
array([[-0.03847249, -0.5622585 , -0.2533469 , -0.11625022,  0.02309722,
        -0.51970744, -0.939214  , -0.70454395, -0.29292732, -0.5248813 ],
       [ 0.18086548,  0.17118181, -0.34515607, -0.518098  ,  0.39097375,
        -0.34556866, -0.80850315, -0.34327775,  0.3201217 ,  0.42236814]],
      dtype=float32)>






<tf.Tensor: id=784, shape=(2, 10), dtype=bool, numpy=
array([[ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True],
       [ True,  True,  True,  True,  True,  True,  True,  True,  True,
         True]])>

GPU计算

注意:需要tensorflow-gpu

gpus = tf.config.experimental.list_physical_devices(device_type='GPU')
cpus = tf.config.experimental.list_physical_devices(device_type='CPU')
print("可用的GPU:",gpus,"\n可用的CPU:", cpus)
可用的GPU: [PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
可用的CPU: [PhysicalDevice(name='/physical_device:CPU:0', device_type='CPU')]

check available device

from tensorflow.python.client import device_lib
print(device_lib.list_local_devices())
[name: "/device:CPU:0"
device_type: "CPU"
memory_limit: 268435456
locality {
}
incarnation: 1237627953479486054
, name: "/device:XLA_CPU:0"
device_type: "XLA_CPU"
memory_limit: 17179869184
locality {
}
incarnation: 14330884921366688297
physical_device_desc: "device: XLA_CPU device"
, name: "/device:XLA_GPU:0"
device_type: "XLA_GPU"
memory_limit: 17179869184
locality {
}
incarnation: 156933604364406105
physical_device_desc: "device: XLA_GPU device"
, name: "/device:GPU:0"
device_type: "GPU"
memory_limit: 1108951040
locality {
  bus_id: 1
  links {
  }
}
incarnation: 3744579298438157716
physical_device_desc: "device: 0, name: NVIDIA Tegra X1, pci bus id: 0000:00:00.0, compute capability: 5.3"
]

specify device

with tf.device('GPU:0'):
    a = tf.constant([1,2,3],dtype=tf.float32)
    b = tf.random.uniform((3,))
    print(tf.exp(a + b) * 2)
tf.Tensor([13.942492 20.270329 65.276825], shape=(3,), dtype=float32)