Ejemplo n.º 1
0
def main():
    z = np.ones((5, 5))
    k = np.ones((3, 3))
    b = 3
    # print(_single_channel_conv(z, k,padding=(1,1)))
    # print(_single_channel_conv(z, k, strides=(2, 2)))
    assert _single_channel_conv(z, k).shape == (3, 3)
    assert _single_channel_conv(z, k, padding=(1, 1)).shape == (5, 5)
    assert _single_channel_conv(z, k, strides=(2, 2)).shape == (2, 2)
    assert _single_channel_conv(z, k, strides=(2, 2),
                                padding=(1, 1)).shape == (3, 3)
    assert _single_channel_conv(z, k, strides=(2, 2),
                                padding=(1, 0)).shape == (3, 2)
    assert _single_channel_conv(z, k, strides=(2, 1),
                                padding=(1, 1)).shape == (3, 5)

    dz = np.ones((1, 1, 3, 3))
    assert _insert_zeros(dz, (1, 1)).shape == (1, 1, 3, 3)
    print(_insert_zeros(dz, (3, 2)))
    assert _insert_zeros(dz, (1, 2)).shape == (1, 1, 3, 5)
    assert _insert_zeros(dz, (2, 2)).shape == (1, 1, 5, 5)
    assert _insert_zeros(dz, (2, 4)).shape == (1, 1, 5, 9)

    z = np.ones((8, 16, 5, 5))
    k = np.ones((16, 32, 3, 3))
    b = np.ones((32))
    assert conv_forward(z, k, b).shape == (8, 32, 3, 3)
    print(conv_forward(z, k, b)[0, 0])

    print(np.argmax(np.array([[1, 2], [3, 4]])))
Ejemplo n.º 2
0
def test_conv_and_max_pooling():
    # 测试卷积和最大池化
    z = np.random.randn(3, 3, 28, 28).astype(np.float64)
    K = np.random.randn(3, 4, 3, 3).astype(np.float64) * 1e-3
    b = np.zeros(4).astype(np.float64)

    next_z = conv_forward(z, K, b)
    y_pred = max_pooling_forward_bak(next_z, pooling=(2, 2))
    y_true = np.ones_like(y_pred)

    from nn.losses import mean_squared_loss
    for i in range(10000):
        # 前向
        next_z = conv_forward(z, K, b)
        y_pred = max_pooling_forward_bak(next_z, pooling=(2, 2))
        # 反向
        loss, dy = mean_squared_loss(y_pred, y_true)
        next_dz = max_pooling_backward_bak(dy, next_z, pooling=(2, 2))
        dK, db, _ = conv_backward(next_dz, K, z)
        K -= 0.001 * dK
        b -= 0.001 * db

        if i % 10 == 0:
            print("i:{},loss:{},mindy:{},maxdy:{}".format(
                i, loss, np.mean(dy), np.max(dy)))

        if np.allclose(y_true, y_pred):
            print("yes")
            break
Ejemplo n.º 3
0
def conv_backward(next_dz, K, z, padding=(0, 0), strides=(1, 1)):
    """
    多通道卷积层的反向过程
    :param next_dz: 卷积输出层的梯度,(N,D,H,W),H,W为卷积输出层的高度和宽度
    :param K: 当前层卷积核,(C,D,k1,k2)
    :param z: 卷积层矩阵,形状(N,C,H,W),N为batch_size,C为通道数
    :param padding: padding
    :param strides: 步长
    :return:
    """
    N, C, H, W = z.shape
    C, D, k1, k2 = K.shape

    # 卷积核梯度
    # dK = np.zeros((C, D, k1, k2))
    padding_next_dz = _insert_zeros(next_dz, strides)

    # 卷积核高度和宽度翻转180度
    flip_K = np.flip(K, (2, 3))
    # 交换C,D为D,C;D变为输入通道数了,C变为输出通道数了
    swap_flip_K = np.swapaxes(flip_K, 0, 1)
    # 增加高度和宽度0填充
    ppadding_next_dz = np.lib.pad(padding_next_dz,
                                  ((0, 0), (0, 0), (k1 - 1, k1 - 1),
                                   (k2 - 1, k2 - 1)),
                                  'constant',
                                  constant_values=0)
    dz = conv_forward(ppadding_next_dz.astype(np.float64),
                      swap_flip_K.astype(np.float64),
                      np.zeros((C, ), dtype=np.float64))

    # 求卷积和的梯度dK
    swap_z = np.swapaxes(z, 0, 1)  # 变为(C,N,H,W)与
    dK = conv_forward(swap_z.astype(np.float64),
                      padding_next_dz.astype(np.float64),
                      np.zeros((D, ), dtype=np.float64))

    # 偏置的梯度
    db = np.sum(np.sum(np.sum(next_dz, axis=-1), axis=-1),
                axis=0)  # 在高度、宽度上相加;批量大小上相加

    # 把padding减掉
    dz = _remove_padding(
        dz,
        padding)  # dz[:, :, padding[0]:-padding[0], padding[1]:-padding[1]]

    return dK / N, db / N, dz