《动手学深度学习》课后作业记录

发布于 2022-06-25  46 次阅读


预备知识

ndarray

#mask
X<Y,X>Y
#3*5*2与3*5张量进行求和,3*5广播为3*5*2
XX=tf.constant([[[1,2,3],[2,4,5],[3,4,5],[4,5,6],[5,6,7]],[[1,2,3],[2,4,5],[3,4,5],[4,5,6],[5,6,7]]])
YY=tf.constant([[1,2,3],[2,4,5],[3,4,5],[4,5,6],[5,6,7]])
XX,YY,XX+YY

pandas

pandas api doc https://pandas.pydata.org/docs/reference/index.html

#主要api位于Series模块
dataAfterDeleteMaxNan=data.drop(labels=data.isnull().sum().idxmax() ,axis=1)
print(dataAfterDeleteMaxNan)
dataAfterDeleteMaxNan.fillna(data.mean())
tf.constant(pd.get_dummies(dataAfterDeleteMaxNan, dummy_na=True))

linear-algebra

#1
X=tf.reshape(tf.range(20, dtype=tf.dtypes.float32), (5, 4))
X_t=tf.transpose(X)
X_t_t=tf.transpose(X_t)
print(X==X_t_t)
#2
Y=tf.reshape(tf.ones(20),(5,4))
Y_t=tf.transpose(Y)
print(tf.transpose(X+Y)==X_t+Y_t)
#3
Z=tf.random.normal ((5,5), dtype=tf.dtypes.float32)
Z_t=tf.transpose(Z)
ZpZ_t=Z+Z_t
print(ZpZ_t==tf.transpose(ZpZ_t))
#4
X=tf.reshape(tf.range(24, dtype=tf.dtypes.float32), (2, 3,4))
print(len(X))
#5
X=tf.reshape(tf.range(60, dtype=tf.dtypes.float32), (5, 3,4))
print(len(X))
#6 不是同形状 需要广播
#A/tf.reduce_sum(A, axis=[1]) 
#7 在哪个维度求和就去掉那个维度
X=tf.reshape(tf.range(24, dtype=tf.dtypes.float32), (2, 3,4))
print(X,tf.reduce_sum(X, axis=0),tf.reduce_sum(X, axis=1),tf.reduce_sum(X, axis=2))
#8 norm指定维度则将指定维度忽略
tf.norm(X,axis=0),tf.norm(X,axis=1),tf.norm(tf.norm(X,axis=0),axis=0),tf.norm(tf.norm(tf.norm(X,axis=0),axis=0)),tf.norm(X)

calculus

#1
def f(x):
    return x**3 - 1/x
def numerical_lim(f, x, h):
    return (f(x + h) - f(x)) / h
plot(x, [f(x),numerical_lim(f,1,0.0001)*(x-1)+f(1) ], 'x', 'f(x)', legend=['f(x)', 'Tangent line (x=1)'])
#2
def f1(x):
    return 3*x**2+5*np.exp(x**2)
numerical_lim(f1, x, 0.001) 
plot(x, [numerical_lim(f1, x, 0.001)], 'x', 'f(x)', legend=['f(x)'])

autograd

#2 运行出错 非持久的GradientTape只能用于计算一组梯度(或雅可比矩阵)
with tf.GradientTape(persistent=True) as t:
    y = x * x
print(t.gradient(y, x)  )
#3
from d2l import tensorflow as d2l
import math
#5
t.gradient(y, x)
x = tf.Variable(tf.range(0, 9, 0.1))
with tf.GradientTape() as t:
    y = tf.math.sin(x)
# 生成图形
d2l.plot(x.numpy(), [tf.math.sin(x).numpy(), t.gradient(y, x).numpy()], 'x', "", legend=['f(x)', "f'(x)"])

线性神经网络

linear-regression-scratch

#1 权重初始化为0无法通过梯度下降来计算梯度
#2 固定电阻 测算不同电压下电流的值 电压值作为feature 电流作为label 由于先验知识可得该线性模型没有bias
#5 数组与一维张量不等价
#7 
def data_iter(batch_size, features, labels):
    #获取features长度
    num_examples = len(features)
    #获取从0到features长度大小的索引列表
    indices = list(range(num_examples))
    # 这些样本是随机读取的,没有特定的顺序
    #打乱索引
    random.shuffle(indices)
    #从0到num_examples 步长 为batch_size 如果样本数量不能整除batch_size 则会浪费一些样本
    for i in range(0, num_examples, batch_size):
        j = tf.constant(indices[i: min(i + batch_size, num_examples)])
        yield tf.gather(features, j), tf.gather(labels, j)

linear-regression-concise

#1
initializer = tf.initializers.RandomNormal(stddev=0.01)
net = tf.keras.Sequential()
net.add(tf.keras.layers.Dense(1, kernel_initializer=initializer))
loss = tf.keras.losses.Huber()
trainer = tf.keras.optimizers.SGD(learning_rate=0.03)
num_epochs = 3
for epoch in range(num_epochs):
    for X, y in data_iter:
        with tf.GradientTape() as tape:
            l = loss(net(X, training=True), y)
        grads = tape.gradient(l, net.trainable_variables)
        trainer.apply_gradients(zip(grads, net.trainable_variables))
    l = loss(net(features), labels)
    print(f'epoch {epoch + 1}, loss {l:f}')

softmax-regression


image-classification-dataset

#1 会影响性能  需要进行多次切割与打乱
#2 

softmax-regression-scratch

#1 754浮点数表示范围
#2 对数函数自变量应大于0
#3 问题一归一化 问题二加上一个极小值
#4 计算复杂度提升

softmax-regression-concise


多层感知机

mlp

#1
x = tf.Variable(tf.range(-8.0, 8.0, 0.1), dtype=tf.float32)
net=tf.keras.layers.PReLU();
y = net(x)
with tf.GradientTape() as t:
    y = net(x)
d2l.plot(x.numpy(),  t.gradient(y, x).numpy(), 'x', 'prelu(x)', figsize=(5, 2.5))
#4 小批量将导致分布不均 

mlp-scratch

#1 num_hiddens参数 单层weight数目增加可能导致过拟合,提高深度比提高广度效果更好
#2 更多的隐藏程即加深网络结构深度
#3 lr过大将导致收敛变慢 过小则无法进行学习 
#4 
#5
#6

mlp-concise

#1
#2 sigmoid对初始值很敏感 10个epoch效果都不好
#3 需要根据不同的激活函数来进行初始化权重 relu一般使用He初始值

underfit-overfit

#1 
#2 
#3 梯度爆炸
#4 在有随机噪声的情况下 就算对训练数据完全拟合 也不可能再测试数据上完全拟合

weight-decay

#1 labmda用于控制惩罚程度 lambda越大则初始损失越大 梯度则越大 梯度过大将导致颠簸 无法收敛至最低点
#2 在同分布的情况下 可以在验证集找lambda
#3 将L2正则项替换为L1
#4
#5 Dropout
#6 

dropout

#1 若首层概率较大则会损失产生较大颠簸现象
#2 增加训练轮数后 不使用dropout时test acc仍然会持续产生颠簸
#3 
#4 暂退法具有随机性 测试时使用暂退法 无法评估模型
#5 两者叠加后曲线更加的平缓了
#6 若激活函数是relu 将导致激活后输出更多的0 输出0的概率比置于激活函数后增加
#7 

backprop


numerical-stability-and-init


environment


kaggle-house-price


深度学习计算

model-construction

#1 不是很理解,原文中实现本来就是list
#2 
class parallelBlock(tf.keras.Model):
    def __init__(self,block1,block2):
        super().__init__()
        self.block1 =  block1
        self.block2 =  block2

    def call(self, X):
        return tf.concat([self.block1(X),self.block2(X)],0)
net = tf.keras.Sequential()    
net.add(parallelBlock(block1= tf.keras.layers.Dense(64, activation=tf.nn.relu),block2= tf.keras.layers.Dense(64, activation=tf.nn.relu)))
net(X)
#3
def genereteMultiBlock(num):
    net=tf.keras.Sequential()    
    for i in range(num):
            net.add(parallelBlock(block1= tf.keras.layers.Dense(64, activation=tf.nn.relu),block2= tf.keras.layers.Dense(64, activation=tf.nn.relu)))
    return net

net = tf.keras.Sequential()   
net.add(genereteMultiBlock(3))
net,net(X)

parameters

#1
class FixedHiddenMLP(tf.keras.Model):
    def __init__(self):
        super().__init__()
        self.flatten = tf.keras.layers.Flatten()
        # 使用`tf.constant`函数创建的随机权重参数在训练期间不会更新(即为常量参数)
        self.rand_weight = tf.constant(tf.random.uniform((20, 20)))
        self.dense = tf.keras.layers.Dense(20, activation=tf.nn.relu)

    def call(self, inputs):
        X = self.flatten(inputs)
        # 使用创建的常量参数以及`relu`和`matmul`函数
        X = tf.nn.relu(tf.matmul(X, self.rand_weight) + 1)
        # 复用全连接层。这相当于两个全连接层共享参数。
        X = self.dense(X)
        # 控制流
        while tf.reduce_sum(tf.math.abs(X)) > 1:
            X /= 2
        return tf.reduce_sum(X)
X = tf.random.uniform((2, 20))
net = tf.keras.Sequential()   
net.add(FixedHiddenMLP())
net(X)
print(net.summary())
print(net.layers[0].summary())
print(net.layers[0].layers[1].get_weights())
#2 https://www.tensorflow.org/api_docs/python/tf/keras/initializers
#3 
#4 有效减少网络参数数量,减小复杂度,防止过拟合

deferred-init

#会立即进行初始化
net = tf.keras.models.Sequential([
    tf.keras.layers.Dense(256, activation=tf.nn.relu,input_shape=(16,)),
    tf.keras.layers.Dense(10),
])
print(net.summary())
[net.layers[i].get_weights() for i in range(len(net.layers))]
#2 tf可以自行推断
#3

custom-layer

#1

read-write

#1 不需要从头训练
#2 保存之前网络前两层的参数 新声明的网络时读取文件自定义前两层的参数
#3 保存为HDF5格式

use-gpu

#1 小计算量任务不占满cpu核心数情况下 主频越高计算越快

卷积神经网络

why-conv

#1
#2 减少了空间特征
#3 补齐
#4 对于频谱图进行卷积
#5 不太适合 空间特征没有图片强烈 

conv-layer

#1 对角矩阵的转置等于其本身
X = tf.Variable(tf.linalg.diag (tf.ones([4])))
K = tf.constant([[0.5, 0],[0, 0.5]])
Y = corr2d(X, K)
Y
corr2d(tf.transpose(X), K)
#2
#3
#4

padding-and-strides

#1
conv2d = tf.keras.layers.Conv2D(1, kernel_size=(3,5), padding='valid',
                                strides=(3, 4))
X,comp_conv2d(conv2d, X),conv2d.get_weights(),comp_conv2d(conv2d, X).shape
#2 
#3 采样率
#4 减少复杂度

channels

#1 感觉和线性结构一个道理
#2 

pooling

#1 可以 kernel的权重为窗口大小分之一
#2 不行 没办法通过指定不一样的权重来实现
#3 
#4 运算逻辑不一样
#5 

lenet

#1 感觉损失函数收敛的更快了

现代卷积神经网络

alexnet

#迭代20次 精确度增加有限
#2
def net():
    return tf.keras.models.Sequential([
        # 这里,我们使用一个11*11的更大窗口来捕捉对象。
        # 同时,步幅为4,以减少输出的高度和宽度。
        # 另外,输出通道的数目远大于LeNet
        tf.keras.layers.Conv2D(filters=24, kernel_size=11, strides=4,
                               activation='relu'),
        tf.keras.layers.MaxPool2D(pool_size=3, strides=2),
        # 减小卷积窗口,使用填充为2来使得输入与输出的高和宽一致,且增大输出通道数
        tf.keras.layers.Conv2D(filters=64, kernel_size=5, padding='same',
                               activation='relu'),
        tf.keras.layers.MaxPool2D(pool_size=3, strides=2),
        # 使用三个连续的卷积层和较小的卷积窗口。
        # 除了最后的卷积层,输出通道的数量进一步增加。
        # 在前两个卷积层之后,汇聚层不用于减少输入的高度和宽度
        tf.keras.layers.Conv2D(filters=128, kernel_size=3, padding='same',
                               activation='relu'),
        tf.keras.layers.Conv2D(filters=128, kernel_size=3, padding='same',
                               activation='relu'),
        tf.keras.layers.Conv2D(filters=64, kernel_size=3, padding='same',
                               activation='relu'),
        tf.keras.layers.MaxPool2D(pool_size=3, strides=2),
        tf.keras.layers.Flatten(),
        # 这里,全连接层的输出数量是LeNet中的好几倍。使用dropout层来减轻过拟合
        tf.keras.layers.Dense(1024, activation='relu'),
        tf.keras.layers.Dropout(0.5),
        tf.keras.layers.Dense(1024, activation='relu'),
        tf.keras.layers.Dropout(0.5),
        # 最后是输出层。由于这里使用Fashion-MNIST,所以用类别数为10,而非论文中的1000
        tf.keras.layers.Dense(10)
    ])
lr, num_epochs = 0.01, 20
d2l.train_ch6(net, train_iter, test_iter, num_epochs, lr, d2l.try_gpu())
#3 显存占用肯定会增加 但是ipython kernel默认占据了很多显存 故看不出差别 精度变化不大

vgg

#1 打印出的是嵌套层输出尺寸
#2 卷积层更多 且维度更大
#3
#4
conv_arch = ((2, 64), (2, 128), (3, 256), (3, 512), (3, 512))
net = vgg(conv_arch)

nin


googlenet


batch-norm


resnet


densenet


 


面向ACG编程