【深度之眼cs231n第七期】笔记(十七)

本文详细记录了验证卷积层、池化层和卷积神经网络的过程,包括前向传播和反向传播的实现。此外,还介绍了空间批量归一化的前向传播及反向传播的数值梯度检查,并提供了相关层的Python实现。
摘要由CSDN通过智能技术生成


ConvolutionalNetworks.ipynb里没有重要的实现,都是 验证
layers.py里有标准卷积层、最大池化层、空间批量归一化层的 实现
fast_layers.py里有标准卷积层、最大池化层的 快速版本,代码没有粘出来,只有 原理
layer_utils.py里有标准卷积层、最大池化层、空间批量归一化层的 组合
cnn.py里有 三层卷积神经网络(有全连接层)。

ConvolutionalNetworks.ipynb

验证卷积层

导包和导入预处理过(减均值)的数据

from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
from cs231n.classifiers.cnn import *
from cs231n.data_utils import get_CIFAR10_data
from cs231n.gradient_check import eval_numerical_gradient_array, eval_numerical_gradient
from cs231n.layers import *
from cs231n.fast_layers import *
from cs231n.solver import Solver

%matplotlib inline
plt.rcParams['figure.figsize'] = (10.0, 8.0) # 画图的默认大小
plt.rcParams['image.interpolation'] = 'nearest' # 若需要插值,使用最临近插值
plt.rcParams['image.cmap'] = 'gray'

# 修改某个文件后,自动重新加载该文件已保存的部分
%load_ext autoreload
%autoreload 2

def rel_error(x, y):
  """ 相对误差 """
  return np.max(np.abs(x - y) / (np.maximum(1e-8, np.abs(x) + np.abs(y))))

# 加载数据
data = get_CIFAR10_data()
for k, v in data.items():
  print('%s: ' % k, v.shape)

卷积层的前向传播

x_shape = (2, 3, 4, 4)
w_shape = (3, 3, 4, 4)
x = np.linspace(-0.1, 0.5, num=np.prod(x_shape)).reshape(x_shape)
w = np.linspace(-0.2, 0.3, num=np.prod(w_shape)).reshape(w_shape)
# 这里的num=3是卷积核的个数,与w_shape[0]一致
b = np.linspace(-0.1, 0.2, num=3)
conv_param = {
   'stride': 2, 'pad': 1}

out, _ = conv_forward_naive(x, w, b, conv_param)
correct_out = np.array([[[[-0.08759809, -0.10987781],
                           [-0.18387192, -0.2109216 ]],
                          [[ 0.21027089,  0.21661097],
                           [ 0.22847626,  0.23004637]],
                          [[ 0.50813986,  0.54309974],
                           [ 0.64082444,  0.67101435]]],
                         [[[-0.98053589, -1.03143541],
                           [-1.19128892, -1.24695841]],
                          [[ 0.69108355,  0.66880383],
                           [ 0.59480972,  0.56776003]],
                          [[ 2.36270298,  2.36904306],
                           [ 2.38090835,  2.38247847]]]])

# 比较输出,相对误差应该为2e-8左右
print('Testing conv_forward_naive')
print('difference: ', rel_error(out, correct_out))
# difference:  2.2121476417505994e-08

通过卷积实现图像预处理(灰度图、边缘检测)

from imageio import imread
from PIL import Image
kitten, puppy = imread('kitten.jpg'), imread('puppy.jpg')
# kitten是长方形的,要转化为正方形。puppy已经是正方形的了
d = kitten.shape[1] - kitten.shape[0]
kitten_cropped = kitten[:, d//2:-d//2, :]

img_size = 200   # 降低分辨率,减少运行时间
x = np.zeros((2, 3, img_size, img_size))
# transpose((2, 0, 1))把颜色通道提前
x[0, :, :, :] = np.array(Image.fromarray(puppy).resize((img_size, img_size))).transpose((2, 0, 1))
x[1, :, :, :] = np.array(Image.fromarray(kitten_cropped).resize((img_size, img_size))).transpose((2, 0, 1))

# 准备两个3*3的卷积核,每个卷积核有3个通道
w = np.zeros((2, 3, 3, 3))
# 第一个卷积核用于获取灰度图像
# 灰度图像=红色*0.3+绿色*0.6+蓝色*0.1
w[0, 0, :, :] = [[0, 0, 0], [0, 0.3, 0], [0, 0, 0]]
w[0, 1, :, :] = [[0, 0, 0], [0, 0.6, 0], [0, 0, 0]]
w[0, 2, :, :] = [[0, 0, 0], [0, 0.1, 0], [0, 0, 0]]
# 第二个卷积核在蓝色通道上提取水平边缘
w[1, 2, :, :] = [[1, 2, 1], [0, 0, 0], [-1, -2, -1]]
# 灰度图像不需要偏置,但边缘检测需要,这样就不会有负数出现了(原注释翻译过来)
# 就算加了128还是会有负数的,其实不加也可以,因为展示图片前有处理
b = np.array([0, 128])

# 通过卷积对图像进行处理
out, _ = conv_forward_naive(x, w, b, {
   'stride': 1, 'pad': 1})
def imshow_noax(img, normalize=True):
    """ 以uint8的格式展示图片,并去掉坐标轴 """
    if normalize:
        img_max, img_min = np.max(img), np.min(img)
        img = 255.0 * (img - img_min) / (img_max - img_min)
    plt.imshow(img.astype('uint8'))
    plt.gca().axis('off')

# 展示原始图片和卷积操作的结果
plt.subplot(2, 3, 1)
imshow_noax(puppy, normalize=False)
plt.title('Original image')
plt.subplot(2, 3, 2)
imshow_noax(out[0, 0])
plt.title('Grayscale')
plt.subplot(2, 3, 3)
imshow_noax(out[0, 1])
plt.title('Edges')
plt.subplot(2, 3, 4)
imshow_noax(kitten_cropped, normalize=False)
plt.subplot(2, 3, 5)
imshow_noax(out[1, 0])
plt.subplot(2, 3, 6)
imshow_noax(out[1, 1])
plt.show()

在这里插入图片描述
卷积层的反向传播

np.random.seed(231)
x = np.random.randn(4, 3, 5, 5)
w = np.random.randn(2, 3, 3, 3)
b = np.random.randn(2,)
dout = np.random.randn(4, 2, 5, 5)
conv_param = {
   'stri
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值