cnn、max_pool和avg_pool Python实现

CNN实现

带batch_size的多通道卷积计算

import numpy as np

def im2col(img, ksize, stride=1):
    N, H, W, C = img.shape
    out_h = (H - ksize) // stride + 1
    out_w = (W - ksize) // stride + 1
    col = np.empty((N * out_h * out_w, ksize * ksize * C))
    outsize = out_w * out_h
    for y in range(out_h):
        y_min = y * stride
        y_max = y_min + ksize
        y_start = y * out_w
        for x in range(out_w):
            x_min = x * stride
            x_max = x_min + ksize
            col[y_start+x::outsize, :] = img[:, y_min:y_max, x_min:x_max, :].reshape(N, -1)
    return col

def conv(X, W, stride=1, padding='valid'):
    FN, ksize, ksize, C = W.shape
    if padding == 'same':
        p = ksize // 2
        X = np.pad(X, ((0, 0), (p, p), (p, p), (0, 0)), 'constant')
    N, H, w, C = X.shape
    col = im2col(X, ksize, stride)
    z = np.dot(col, W.reshape(W.shape[0], -1).transpose())
    z = z.reshape(N, z.shape[0] // N, -1)
    out_h = (H - ksize) // stride + 1
    return z.reshape(N, out_h, -1 , FN)

A = np.random.randint(0, 9, (2*3*3*3)).reshape(2, 3, 3, 3)
ken = np.random.randint(0, 9, (6*2*2*3)).reshape(6,2,2,3)
print(conv(A, ken, 1).shape)
import numpy as np
from numpy.lib.stride_tricks import as_strided
def Conv2d_(X, kernel, stride, padding=0):
    if padding:
        X = np.pad(X, pad_width=((0, 0), (padding, padding), (padding, padding), (0, 0)), mode='constant', constant_values=0)
    N, C, H, W = X.shape
    kernel_n, kernel_c, kernel_size_h, kernel_size_w = kernel.shape
    output_shape = (N, kernel_n, (H-kernel_size_h)//stride+1, (W-kernel_size_w)//stride+1)
    kernel_size = (kernel_size_w, kernel_size_h)

    img_W = as_strided(X, shape=kernel_size+(N, C, output_shape[-2], output_shape[-1]),
                       strides=(X.strides[0], X.strides[1], stride*X.strides[2], stride*X.strides[3])+X.strides[-2:])
    img_W = img_W.reshape(-1, kernel_c*kernel_size_h*kernel_size_w)
    Z = np.dot(img_W, kernel.reshape(kernel_n, -1).transpose())
    return Z.reshape(output_shape)
   
A = np.random.randint(0, 9, (2*3*3*3)).reshape(2, 3, 3, 3)
ken = np.random.randint(0, 9, (6*2*2*3)).reshape(6,3,2,2)
print(Conv2d_(A, ken, 1).shape)
# 平面卷积计算
import numpy as np
from numpy.lib.stride_tricks import as_strided

def Conv2d(img, kernel, stride, padding=0):
    if padding:
        img = np.pad(img, pad_width=padding, mode='constant')
    kernel_size_h, kernel_size_w = len(kernel[0]), len(kernel[1])
    output_shape = ((img.shape[0]-kernel_size_h)//stride+1, (img.shape[1]-kernel_size_w)//stride+1)
    kernel_size = (kernel_size_h, kernel_size_w)
    img_W = as_strided(img, shape=kernel_size+output_shape,
                       strides=(stride*img.strides[0], stride*img.strides[1])+img.strides)
    img_W = img_W.reshape(-1, *kernel_size)
    return np.tensordot(img_W, kernel).reshape(output_shape)

A = np.array([[1, 1, 1, 1, 1], [1, 1, 3, 1, 1], [1, 2, 1, 1, 1], [1, 1, 1, 1, 1]])  # 4行5列
ken = np.array([[2, 4], [2, 1]])
print(Conv2d(A, ken, 2, 1))

pool实现

numpy实现

import numpy as np
from numpy.lib.stride_tricks import as_strided

def pool2d(A, kernel_size, stride, padding, pool_mode='max'):
	if padding:
	    A = np.pad(A, padding, 'constant')

    output_shape = ((A.shape[0]-kernel_size)//stride+1, (A.shape[1]-kernel_size)//stride+1)
    kernel_size = (kernel_size, kernel_size)
    A_w = as_strided(A, shape=output_shape+kernel_size,
                     strides=(stride*A.strides[0], stride*A.strides[1])+A.strides)
    A_w = A_w.reshape(-1, *kernel_size)

    if pool_mode == 'max':
        return A_w.max(axis=(1,2)).reshape(output_shape)
    if pool_mode == 'avg':
        return A_w.mean(axis=(1,2)).reshape(output_shape)


A = np.array([[1, 1, 2, 4],
              [5, 6, 7, 8],
              [3, 2, 1, 0],
              [1, 2, 3, 4]])

print(pool2d(A, kernel_size=2, stride=2, padding=0, pool_mode='avg'))

普通实现

from itertools import product
def max_pool(nums):
    m, n = len(nums), len(nums[0])
    ans = [[0]*(n//2) for _ in range(m//2)]
    for i, j in product(range(0, m-1, 2), range(0, n-1, 2)):
        maxN = float('-inf')
        for k, l in product(range(i, min(m, i+2)), range(j, min(n, j+2))):
            maxN = max(maxN, nums[k][l])
        ans[i//2][j//2] = maxN

    return ans

def avg_pool(nums):
    m, n = len(nums), len(nums[0])
    ans = [[0]*n for _ in range(m)]
    for i, j in product(range(m), range(n)):
        total = 0
        cnt = 0
        for k, l in product(range(max(0, i-1), min(m, i+2)), range(max(0, j-1), min(n, j+2))):
            total += nums[k][l]
            cnt += 1
        ans[i][j] = total//cnt
    return ans

def avg_pool_new(nums):
    m, n = len(nums), len(nums[0])
    ans = [[0]*n for _ in range(m)]
    prefix = [[0]*(n+1) for _ in range(m+1)]
    for i, j in product(range(1, m+1), range(1, n+1)):
        prefix[i][j] = prefix[i-1][j] + prefix[i][j-1] - prefix[i-1][j-1] + nums[i-1][j-1]

    for i, j in product(range(m), range(n)):
        x1, y1 = max(0, i-1), max(0, j-1)
        x2, y2 = min(m-1, i+1), min(n-1, j+1)

        total = prefix[x2+1][y2+1] - prefix[x1][y2+1] - prefix[x2+1][y1] + prefix[x1][y1]
        cnt = (x2-x1+1)*(y2-y1+1)
        ans[i][j] = total // cnt
    return ans

# nums = [[1,2,3], [4,5,6], [7,8,9]]
nums = [[1,2,3,4],[5,6,7,8], [9,10,11,12], [13,14,15,16]]
print(nums)
print(max_pool(nums))
print(avg_pool(nums))
print(avg_pool_new(nums))
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fighting_1997

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值