numpy实现卷积网络

import numpy as np
class conv():
    def __init__(self,in_channles,out_channles,kernel=3,stride=1,padding=0):
        self.in_channles = in_channles
        self.out_channles =out_channles
        self.kernel = kernel
        self.stride = stride
        self.padding = padding
        self.filter = np.random.random((3,3,3))
        self.bias = np.zeros(out_channles)
    def numpy_conv(self,inputs,filter,out_shape):
        filter_size = filter.shape[0]
        result = np.zeros(out_shape)
        H, W = out_shape
        for r in range(0, H):
            for c in range(0, W):
                # 池化大小的输入区域
                cur_input = inputs[r*self.stride:r*self.stride + filter_size,
                            c*self.stride:c*self.stride + filter_size]
                cur_output = cur_input * filter
                conv_sum = np.sum(cur_output)
                result[r, c] = conv_sum
        return result

    def forward(self, inputs):
        N, C, H, W = inputs.shape
        assert C==self.in_channles,"wwwwww %s %s"%(C,self.in_channles)
        out_H = int((H - self.kernel + 2 * self.padding) / self.stride) + 1
        out_W = int((W - self.kernel + 2 * self.padding) / self.stride) + 1
        # print(out_H,out_W)
        result = np.zeros([N,self.out_channles, out_H, out_W], np.float32)
        inputs = np.pad(inputs, ((0, 0),(0, 0), (self.padding, self.padding), (self.padding, self.padding)), 'constant',
                        constant_values=(0, 0))

        for n in range(N):
            for i in range(self.out_channles):
                result[n, i, :, :] = self.bias[i]
                for j in range(self.in_channles):
                    channel_data = inputs[n,j]
                    # 采用上面对逻辑,单核单通道卷积,然后累计
                    result[n, i, :, :] += self.numpy_conv(channel_data, self.filter[i][j] ,(out_H,out_W))

        return result
class max_pool():
    def __init__(self,pooling=(2,2), strides=(2, 2), padding=(0, 0)):
        self.pooling = pooling
        self.strides = strides
        self.padding = padding
    def forward(self,z):

        z = np.pad(z, ((0, 0),(0, 0), (self.padding[0], self.padding[0]), (self.padding[1], self.padding[1])), 'constant',
                        constant_values=(0, 0))
        N, C, H, W = z.shape
        out_H = int(H/2)
        out_W = int(W / 2)
        pool_z = np.zeros((N, C, out_H, out_W))
        for i in range(N):
            for j in range(C):
                for oi in range(out_H):
                    for oj in range(out_W):
                        pool_z[i,j,oi,oj] = np.max(z[i,j,
                                                        oi*self.strides[0]:  oi*self.strides[0]+ self.pooling[0],
                                                        oj*self.strides[1]:  oj*self.strides[1]+ self.pooling[1]
                                                ])
        return pool_z
def relu(x):
    return np.maximum(x, 0)
class BN():
    def __init__(self,channel,weight=[],bias=[],eps=1e-05):
        self.channel = channel
        self.weight = weight
        self.bias = bias
        self.eps =eps
        self.running_mean = []
        self.running_var = []
    def forward(self,x):



        data = x.transpose((1, 0, 2, 3)).reshape(self.channel, -1)
        if len(self.running_mean)==0 and len(self.running_var)==0:
            mu1 = data.mean(axis=1).reshape(1, self.channel, 1, 1)
            std1 = data.std(axis=1).reshape(1, self.channel, 1, 1)
        else:
            mu1  = self.running_mean.reshape(1, self.channel, 1, 1)
            std1 = np.sqrt(self.running_var).reshape(1, self.channel, 1, 1)

        if not len(self.weight) and not len(self.bias):
            numpy_bn = (x - mu1) / (std1 + self.eps)
        else:
            self.weight = self.weight.reshape(1, self.channel, 1, 1)
            self.bias= self.bias.reshape(1, self.channel, 1, 1)
            numpy_bn = (x - mu1) / (std1 + self.eps)*self.weight + self.bias
        return numpy_bn
class Liner():
    def __init__(self,in_features,out_features,bias=0):
        self.in_features =in_features
        self.out_features = out_features
        self.weight = np.zeros((in_features,out_features))
        self.bias = np.zeros((in_features,out_features))
    def forward(self,x):
        return np.dot(x,self.weight.T) + self.bias
def max_pooling_forward(z, pooling, strides=(2, 2), padding=(0, 0)):
    """
    最大池化前向过程
    :param z: 卷积层矩阵,形状(N,C,H,W),N为batch_size,C为通道数
    :param pooling: 池化大小(k1,k2)
    :param strides: 步长
    :param padding: 0填充
    :return:
    """
    N, C, H, W = z.shape
    # 零填充
    padding_z = np.lib.pad(z, ((0, 0), (0, 0), (padding[0], padding[0]), (padding[1], padding[1])), 'constant', constant_values=0)

    # 输出的高度和宽度
    out_h = (H + 2 * padding[0] - pooling[0]) // strides[0] + 1
    out_w = (W + 2 * padding[1] - pooling[1]) // strides[1] + 1

    pool_z = np.zeros((N, C, out_h, out_w))

    for n in np.arange(N):
        for c in np.arange(C):
            for i in np.arange(out_h):
                for j in np.arange(out_w):
                    pool_z[n, c, i, j] = np.max(padding_z[n, c,
                                                          strides[0] * i:strides[0] * i + pooling[0],
                                                          strides[1] * j:strides[1] * j + pooling[1]])
    return pool_z
# backbone.0.weight
# backbone.0.bias
# backbone.1.weight
# backbone.1.bias
# backbone.1.running_mean
# backbone.1.running_var
# backbone.1.num_batches_tracked
# backbone.4.weight
# backbone.4.bias
# backbone.5.weight
# backbone.5.bias
# backbone.5.running_mean
# backbone.5.running_var
# backbone.5.num_batches_tracked
# backbone.8.weight
# backbone.8.bias
# backbone.9.weight
# backbone.9.bias
# backbone.9.running_mean
# backbone.9.running_var
# backbone.9.num_batches_tracked
# classifier.0.weight
# classifier.0.bias
class my_net():
    def __init__(self,weight):
        self.weight = weight
        self.relu = relu
        self.net = self.createNet()
    def createNet(self):
        self.conv1 = conv(3, 16, 3, 2, 1)
        self.bn1 = BN(16)
        self.pool1 = max_pool()
        self.conv2 = conv(16, 32, 3, 1)
        self.bn2 = BN(32)
        self.pool2 = max_pool()
        self.conv3 = conv(32, 32, 3, 2, 1)
        self.bn3 = BN(32)
        self.fc = Liner(32*4*4,2)

        self.inint_weight()
    def inint_weight(self):
        self.conv1.filter = self.weight['backbone.0.weight'].cpu().numpy()
        self.conv1.bias = self.weight['backbone.0.bias'].cpu().numpy()
        self.bn1.weight = self.weight['backbone.1.weight'].cpu().numpy()
        self.bn1.bias = self.weight['backbone.1.bias'].cpu().numpy()
        self.bn1.running_mean= self.weight['backbone.1.running_mean'].cpu().numpy()
        self.bn1.running_var= self.weight['backbone.1.running_var'].cpu().numpy()
        self.conv2.filter = self.weight['backbone.4.weight'].cpu().numpy()
        self.conv2.bias = self.weight['backbone.4.bias'].cpu().numpy()
        self.bn2.weight = self.weight['backbone.5.weight'].cpu().numpy()
        self.bn2.bias = self.weight['backbone.5.bias'].cpu().numpy()
        self.bn2.running_mean = self.weight['backbone.5.running_mean'].cpu().numpy()
        self.bn2.running_var = self.weight['backbone.5.running_var'].cpu().numpy()
        self.conv3.filter = self.weight['backbone.8.weight'].cpu().numpy()
        self.conv3.bias = self.weight['backbone.8.bias'].cpu().numpy()
        self.bn3.weight = self.weight['backbone.9.weight'].cpu().numpy()
        self.bn3.bias = self.weight['backbone.9.bias'].cpu().numpy()
        self.bn3.running_mean = self.weight['backbone.9.running_mean'].cpu().numpy()
        self.bn3.running_var = self.weight['backbone.9.running_var'].cpu().numpy()
        self.fc.weight = self.weight['classifier.0.weight'].cpu().numpy()
        self.fc.bias = self.weight['classifier.0.bias'].cpu().numpy()

    def forward(self,x):
        x = self.conv1.forward(x)
        x = self.bn1.forward(x)
        x = self.relu(x)
        x = self.pool1.forward(x)
        x = self.conv2.forward(x)
        x = self.bn2.forward(x)
        x = self.relu(x)
        x = self.pool2.forward(x)
        x = self.conv3.forward(x)
        x = self.bn3.forward(x)
        x = self.relu(x).reshape(1,-1)
        x = self.fc.forward(x)
        return x






if __name__=="__main__":


    import torch
    from PIL import Image
    from torchvision import transforms
    path = "4.jpeg"
    img = Image.open(path).convert('RGB')
    transform = transforms.Compose([
        transforms.Resize((64, 64)),
        transforms.ToTensor()
        ])
    img = transform(img)
    img = img.unsqueeze(0).numpy()
    print(img.shape)
    a = torch.load('112.pth')
    net = my_net(a)
    import time
    t =time.time()
    print(net.forward(img))
    print(time.time()-t)





使用文件连接:

https://download.csdn.net/download/weixin_38730719/20719481

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
定理是指信号处理中的一种重要定理,它描述了在时域与频域之间的卷关系。在数学中,卷定理可以表示为: $$ \mathcal{F}^{-1}\{\mathcal{F}\{f(x)g(x)\}\} = f(x) * g(x) $$ 其中,$f(x)$ 和 $g(x)$ 是两个函数,$\mathcal{F}\{f(x)\}$ 和 $\mathcal{F}\{g(x)\}$ 分别是它们的傅里叶变换,$*$ 表示卷运算,$\mathcal{F}^{-1}\{F(k)\}$ 表示 $F(k)$ 的傅里叶反变换。 在使用卷定理时,我们可以先将 $f(x)$ 和 $g(x)$ 分别进行傅里叶变换,然后将它们的乘取反变换,得到的结果即为 $f(x)$ 和 $g(x)$ 的卷。 下面我们使用 numpy 来验证卷定理。假设我们有两个函数 $f(x)$ 和 $g(x)$,它们分别为: $$ f(x) = \begin{cases} 1, & 0 \leq x \leq 1 \\ 0, & \text{otherwise} \end{cases} $$ $$ g(x) = \begin{cases} 2, & 0 \leq x \leq 2 \\ 0, & \text{otherwise} \end{cases} $$ 首先,我们可以用 numpy 来生成这两个函数的离散数据: ```python import numpy as np x = np.linspace(0, 5, 50) f = np.zeros_like(x) f[(x >= 0) & (x <= 1)] = 1 g = np.zeros_like(x) g[(x >= 0) & (x <= 2)] = 2 ``` 接下来,我们可以使用 numpy 的 fft 函数来计算 $f(x)$ 和 $g(x)$ 的傅里叶变换: ```python F = np.fft.fft(f) G = np.fft.fft(g) ``` 然后,我们可以将 $F(k)$ 和 $G(k)$ 相乘,得到它们的乘: ```python FG = F * G ``` 最后,我们可以使用 numpy 的 ifft 函数来计算 $FG(k)$ 的傅里叶反变换,得到 $f(x)$ 和 $g(x)$ 的卷: ```python fg = np.fft.ifft(FG).real ``` 我们还可以使用 numpy 的 convolve 函数来计算 $f(x)$ 和 $g(x)$ 的卷,用于验证卷定理的正确性: ```python conv_fg = np.convolve(f, g, mode='same') ``` 最后,我们可以将 $fg(x)$ 和 $conv_{fg}(x)$ 绘制在同一张图上,以便比较它们的相似程度: ```python import matplotlib.pyplot as plt plt.plot(x, fg, label='FFT Convolution') plt.plot(x, conv_fg, label='Numpy Convolution') plt.legend() plt.show() ``` 完整代码如下: ```python import numpy as np import matplotlib.pyplot as plt # 生成函数 f(x) 和 g(x) 的离散数据 x = np.linspace(0, 5, 50) f = np.zeros_like(x) f[(x >= 0) & (x <= 1)] = 1 g = np.zeros_like(x) g[(x >= 0) & (x <= 2)] = 2 # 计算傅里叶变换 F = np.fft.fft(f) G = np.fft.fft(g) # 计算傅里叶变换的乘 FG = F * G # 计算傅里叶反变换,得到卷结果 fg = np.fft.ifft(FG).real # 使用 numpy 的 convolve 函数计算卷结果,用于比较 conv_fg = np.convolve(f, g, mode='same') # 绘制卷结果的图像 plt.plot(x, fg, label='FFT Convolution') plt.plot(x, conv_fg, label='Numpy Convolution') plt.legend() plt.show() ``` 运行以上代码,可以得到如下的图像: ![image.png](attachment:image.png) 从图像中可以看出,使用傅里叶变换得到的卷结果与使用 numpy 的 convolve 函数得到的卷结果非常相似,这验证了卷定理的正确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值