纯NumPy代码从头实现简单的卷积神经网络

2023-05-16

在某些情况下,使用 ML/DL 库中已经存在的模型可能会很便捷。但为了更好地控制和理解模型,你应该自己去实现它们。本文展示了如何仅使用 NumPy 库来实现 CNN。

卷积神经网络(CNN)是分析图像等多维信号的当前最优技术。目前已有很多库可以实现 CNN,如 TensorFlow 和 Keras 等。这种库仅提供一个抽象的 API,因此可以大大降低开发难度,并避免实现的复杂性,不过使用这种库的开发人员无法接触到一些细节,这些细节可能在实践中很重要。

有时,数据科学家必须仔细查看这些细节才能提高性能。在这种情况下,最好自己亲手构建此类模型,这可以帮助你最大程度地控制网络。因此在本文中,我们将仅使用 NumPy 尝试创建 CNN。我们会创建三个层,即卷积层(简称 conv)、ReLU 层和最大池化层。所涉及的主要步骤如下:

  • 读取输入图像。准备滤波器。
  • 卷积层:使用滤波器对输入图像执行卷积操作。
  • ReLU 层:将 ReLU 激活函数应用于特征图(卷积层的输出)。
  • 最大池化层:在 ReLU 层的输出上应用池化操作。
import skimage.data  
from skimage import io
import matplotlib.pyplot as plt
 # Reading the image  
img = skimage.data.chelsea()  
# Converting the image into gray.  
img = skimage.color.rgb2gray(img)
print(img.shape)
io.imshow(img)
plt.show()

这里写图片描述
代码参考:https://github.com/ahmedfgad/NumPyCNN

def conv_(img, conv_filter):
    filter_size = conv_filter.shape[1]
    result = numpy.zeros((img.shape))
    #Looping through the image to apply the convolution operation.
    for r in numpy.uint16(numpy.arange(filter_size/2, 
                          img.shape[0]-filter_size/2)):
        for c in numpy.uint16(numpy.arange(filter_size/2, 
                                           img.shape[1]-filter_size/2)):
            """
            Getting the current region to get multiplied with the filter.
            How to loop through the image and get the region based on 
            the image and filer sizes is the most tricky part of convolution.
            """
            curr_region = img[r-numpy.uint16(numpy.floor(filter_size/2)):r+numpy.uint16(numpy.ceil(filter_size/2)), 
                              c-numpy.uint16(numpy.floor(filter_size/2)):c+numpy.uint16(numpy.ceil(filter_size/2))]
            #Element-wise multipliplication between the current region and the filter.
            curr_result = curr_region * conv_filter
            conv_sum = numpy.sum(curr_result) #Summing the result of multiplication.
            result[r, c] = conv_sum #Saving the summation in the convolution layer feature map.

    #Clipping the outliers of the result matrix.
    final_result = result[numpy.uint16(filter_size/2):result.shape[0]-numpy.uint16(filter_size/2), 
                          numpy.uint16(filter_size/2):result.shape[1]-numpy.uint16(filter_size/2)]
    return final_result
def conv(img, conv_filter):
    if len(img.shape) > 2 or len(conv_filter.shape) > 3: # Check if number of image channels matches the filter depth.
        if img.shape[-1] != conv_filter.shape[-1]:
            print("Error: Number of channels in both image and filter must match.")
            sys.exit()
    if conv_filter.shape[1] != conv_filter.shape[2]: # Check if filter dimensions are equal.
        print('Error: Filter must be a square matrix. I.e. number of rows and columns must match.')
        sys.exit()
    if conv_filter.shape[1]%2==0: # Check if filter diemnsions are odd.
        print('Error: Filter must have an odd size. I.e. number of rows and columns must be odd.')
        sys.exit()

    # An empty feature map to hold the output of convolving the filter(s) with the image.
    feature_maps = numpy.zeros((img.shape[0]-conv_filter.shape[1]+1, 
                                img.shape[1]-conv_filter.shape[1]+1, 
                                conv_filter.shape[0]))

    # Convolving the image by the filter(s).
    for filter_num in range(conv_filter.shape[0]):
        print("Filter ", filter_num + 1)
        curr_filter = conv_filter[filter_num, :] # getting a filter from the bank.
        """ 
        Checking if there are mutliple channels for the single filter.
        If so, then each channel will convolve the image.
        The result of all convolutions are summed to return a single feature map.
        """
        if len(curr_filter.shape) > 2:
            conv_map = conv_(img[:, :, 0], curr_filter[:, :, 0]) # Array holding the sum of all feature maps.
            for ch_num in range(1, curr_filter.shape[-1]): # Convolving each channel with the image and summing the results.
                conv_map = conv_map + conv_(img[:, :, ch_num], 
                                  curr_filter[:, :, ch_num])
        else: # There is just a single channel in the filter.
            conv_map = conv_(img, curr_filter)
        feature_maps[:, :, filter_num] = conv_map # Holding feature map with the current filter.
    return feature_maps # Returning all feature maps.


def pooling(feature_map, size=2, stride=2):
    #Preparing the output of the pooling operation.
    pool_out = numpy.zeros((numpy.uint16((feature_map.shape[0]-size+1)/stride),
                            numpy.uint16((feature_map.shape[1]-size+1)/stride),
                            feature_map.shape[-1]))
    for map_num in range(feature_map.shape[-1]):
        r2 = 0
        for r in numpy.arange(0,feature_map.shape[0]-size-1, stride):
            c2 = 0
            for c in numpy.arange(0, feature_map.shape[1]-size-1, stride):
                pool_out[r2, c2, map_num] = numpy.max(feature_map[r:r+size,  c:c+size])
                c2 = c2 + 1
            r2 = r2 +1
    return pool_out

def relu(feature_map):
    #Preparing the output of the ReLU activation function.
    relu_out = numpy.zeros(feature_map.shape)
    for map_num in range(feature_map.shape[-1]):
        for r in numpy.arange(0,feature_map.shape[0]):
            for c in numpy.arange(0, feature_map.shape[1]):
                relu_out[r, c, map_num] = numpy.max(feature_map[r, c, map_num], 0)
    return relu_out
import skimage.data
import numpy
import matplotlib

# Reading the image
#img = skimage.io.imread("test.jpg")
#img = skimage.data.checkerboard()
img = skimage.data.chelsea()
#img = skimage.data.camera()

# Converting the image into gray.
img = skimage.color.rgb2gray(img)

# First conv layer
#l1_filter = numpy.random.rand(2,7,7)*20 # Preparing the filters randomly.
l1_filter = numpy.zeros((2,3,3))
l1_filter[0, :, :] = numpy.array([[[-1, 0, 1], 
                                   [-1, 0, 1], 
                                   [-1, 0, 1]]])
l1_filter[1, :, :] = numpy.array([[[1,   1,  1], 
                                   [0,   0,  0], 
                                   [-1, -1, -1]]])

print("\n**Working with conv layer 1**")
l1_feature_map =conv(img, l1_filter)
print("\n**ReLU**")
l1_feature_map_relu =relu(l1_feature_map)
print("\n**Pooling**")
l1_feature_map_relu_pool =pooling(l1_feature_map_relu, 2, 2)
print("**End of conv layer 1**\n")

# Second conv layer
l2_filter = numpy.random.rand(3, 5, 5, l1_feature_map_relu_pool.shape[-1])
print("\n**Working with conv layer 2**")
l2_feature_map = conv(l1_feature_map_relu_pool, l2_filter)
print("\n**ReLU**")
l2_feature_map_relu = relu(l2_feature_map)
print("\n**Pooling**")
l2_feature_map_relu_pool = pooling(l2_feature_map_relu, 2, 2)
print("**End of conv layer 2**\n")

# Third conv layer
l3_filter = numpy.random.rand(1, 7, 7, l2_feature_map_relu_pool.shape[-1])
print("\n**Working with conv layer 3**")
l3_feature_map =conv(l2_feature_map_relu_pool, l3_filter)
print("\n**ReLU**")
l3_feature_map_relu =relu(l3_feature_map)
print("\n**Pooling**")
l3_feature_map_relu_pool =pooling(l3_feature_map_relu, 2, 2)
print("**End of conv layer 3**\n")

# Graphing results
fig0, ax0 = matplotlib.pyplot.subplots(nrows=1, ncols=1)
ax0.imshow(img).set_cmap("gray")
ax0.set_title("Input Image")
ax0.get_xaxis().set_ticks([])
ax0.get_yaxis().set_ticks([])
matplotlib.pyplot.savefig("in_img.png", bbox_inches="tight")
matplotlib.pyplot.close(fig0)

# Layer 1
fig1, ax1 = matplotlib.pyplot.subplots(nrows=3, ncols=2)
ax1[0, 0].imshow(l1_feature_map[:, :, 0]).set_cmap("gray")
ax1[0, 0].get_xaxis().set_ticks([])
ax1[0, 0].get_yaxis().set_ticks([])
ax1[0, 0].set_title("L1-Map1")

ax1[0, 1].imshow(l1_feature_map[:, :, 1]).set_cmap("gray")
ax1[0, 1].get_xaxis().set_ticks([])
ax1[0, 1].get_yaxis().set_ticks([])
ax1[0, 1].set_title("L1-Map2")

ax1[1, 0].imshow(l1_feature_map_relu[:, :, 0]).set_cmap("gray")
ax1[1, 0].get_xaxis().set_ticks([])
ax1[1, 0].get_yaxis().set_ticks([])
ax1[1, 0].set_title("L1-Map1ReLU")

ax1[1, 1].imshow(l1_feature_map_relu[:, :, 1]).set_cmap("gray")
ax1[1, 1].get_xaxis().set_ticks([])
ax1[1, 1].get_yaxis().set_ticks([])
ax1[1, 1].set_title("L1-Map2ReLU")

ax1[2, 0].imshow(l1_feature_map_relu_pool[:, :, 0]).set_cmap("gray")
ax1[2, 0].get_xaxis().set_ticks([])
ax1[2, 0].get_yaxis().set_ticks([])
ax1[2, 0].set_title("L1-Map1ReLUPool")

ax1[2, 1].imshow(l1_feature_map_relu_pool[:, :, 1]).set_cmap("gray")
ax1[2, 0].get_xaxis().set_ticks([])
ax1[2, 0].get_yaxis().set_ticks([])
ax1[2, 1].set_title("L1-Map2ReLUPool")

matplotlib.pyplot.savefig("L1.png", bbox_inches="tight")
matplotlib.pyplot.close(fig1)

# Layer 2
fig2, ax2 = matplotlib.pyplot.subplots(nrows=3, ncols=3)
ax2[0, 0].imshow(l2_feature_map[:, :, 0]).set_cmap("gray")
ax2[0, 0].get_xaxis().set_ticks([])
ax2[0, 0].get_yaxis().set_ticks([])
ax2[0, 0].set_title("L2-Map1")

ax2[0, 1].imshow(l2_feature_map[:, :, 1]).set_cmap("gray")
ax2[0, 1].get_xaxis().set_ticks([])
ax2[0, 1].get_yaxis().set_ticks([])
ax2[0, 1].set_title("L2-Map2")

ax2[0, 2].imshow(l2_feature_map[:, :, 2]).set_cmap("gray")
ax2[0, 2].get_xaxis().set_ticks([])
ax2[0, 2].get_yaxis().set_ticks([])
ax2[0, 2].set_title("L2-Map3")

ax2[1, 0].imshow(l2_feature_map_relu[:, :, 0]).set_cmap("gray")
ax2[1, 0].get_xaxis().set_ticks([])
ax2[1, 0].get_yaxis().set_ticks([])
ax2[1, 0].set_title("L2-Map1ReLU")

ax2[1, 1].imshow(l2_feature_map_relu[:, :, 1]).set_cmap("gray")
ax2[1, 1].get_xaxis().set_ticks([])
ax2[1, 1].get_yaxis().set_ticks([])
ax2[1, 1].set_title("L2-Map2ReLU")

ax2[1, 2].imshow(l2_feature_map_relu[:, :, 2]).set_cmap("gray")
ax2[1, 2].get_xaxis().set_ticks([])
ax2[1, 2].get_yaxis().set_ticks([])
ax2[1, 2].set_title("L2-Map3ReLU")

ax2[2, 0].imshow(l2_feature_map_relu_pool[:, :, 0]).set_cmap("gray")
ax2[2, 0].get_xaxis().set_ticks([])
ax2[2, 0].get_yaxis().set_ticks([])
ax2[2, 0].set_title("L2-Map1ReLUPool")

ax2[2, 1].imshow(l2_feature_map_relu_pool[:, :, 1]).set_cmap("gray")
ax2[2, 1].get_xaxis().set_ticks([])
ax2[2, 1].get_yaxis().set_ticks([])
ax2[2, 1].set_title("L2-Map2ReLUPool")

ax2[2, 2].imshow(l2_feature_map_relu_pool[:, :, 2]).set_cmap("gray")
ax2[2, 2].get_xaxis().set_ticks([])
ax2[2, 2].get_yaxis().set_ticks([])
ax2[2, 2].set_title("L2-Map3ReLUPool")

matplotlib.pyplot.savefig("L2.png", bbox_inches="tight")
matplotlib.pyplot.close(fig2)

# Layer 3
fig3, ax3 = matplotlib.pyplot.subplots(nrows=1, ncols=3)
ax3[0].imshow(l3_feature_map[:, :, 0]).set_cmap("gray")
ax3[0].get_xaxis().set_ticks([])
ax3[0].get_yaxis().set_ticks([])
ax3[0].set_title("L3-Map1")

ax3[1].imshow(l3_feature_map_relu[:, :, 0]).set_cmap("gray")
ax3[1].get_xaxis().set_ticks([])
ax3[1].get_yaxis().set_ticks([])
ax3[1].set_title("L3-Map1ReLU")

ax3[2].imshow(l3_feature_map_relu_pool[:, :, 0]).set_cmap("gray")
ax3[2].get_xaxis().set_ticks([])
ax3[2].get_yaxis().set_ticks([])
ax3[2].set_title("L3-Map1ReLUPool")

matplotlib.pyplot.savefig("L3.png", bbox_inches="tight")
matplotlib.pyplot.close(fig3)

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

纯NumPy代码从头实现简单的卷积神经网络 的相关文章

  • python matplotlib 保存图形而不显示

    我想创建一个直方图并将其保存到文件中而不将其显示在屏幕上 我现在拥有的代码默认显示该图 我找不到任何方法来抑制显示该图 我也尝试过 pyplot hist nrs 也有同样的问题 import math time matplotlib py
  • 如何计算Numpy数组中特定范围内的值?

    我有一个 NumPy 值数组 我想计算有多少个值在特定范围内 例如 x25 我已阅读有关计数器的信息 但它似乎仅对特定值有效 对值范围无效 我已经搜索过 但没有找到任何关于我的具体问题的信息 如果有人能指出我正确的文档 我将不胜感激 谢谢
  • 将 3D 矩阵转换为级联 2D 矩阵

    我有一个3Dpython中的矩阵如下 import numpy as np a np ones 2 2 3 a 0 0 0 2 a 0 0 1 3 a 0 0 2 4 我想转换这个3D矩阵到一组2D矩阵 我努力了np reshape但这并没
  • 加速 Numpy 数组上的循环

    在我的代码中 我有一个 for 循环 它对多维 numpy 数组进行索引 并使用每次迭代时获得的子数组进行一些操作 看起来像这样 for sub in Arr do stuff using sub 现在使用完成的东西sub是完全矢量化的 所
  • 有没有办法降低 scipy/numpy 精度以减少内存消耗?

    在我的 64 位 Debian Lenny 系统 4GByte RAM 4GByte 交换分区 上 我可以成功执行以下操作 v array 10000 random 512 512 512 dtype np int16 f fftn v 但
  • 如何在 numpy 中有效地实现 x[i][j] = y[i+j] ?

    Let x是形状为 A B 的矩阵并且y是一个大小为 A B 1 的数组 for i in range A for j in range B x i j y i j 如何使用 numpy 中的函数有效地实现等效代码 方法 1 Using S
  • 对 numpy 数组的每 n 个元素求平均值

    我有一个 numpy 数组 我想创建一个新数组 它是每个连续三元组元素的平均值 因此 新数组的大小将是原始数组的三分之一 举个例子 np array 1 2 3 1 2 3 1 2 3 应该返回数组 np array 2 2 2 谁能建议一
  • IndexError:布尔索引与维度 0 上的索引数组不匹配

    在我将 Numpy 更新到 1 13 1 之前 我的代码工作正常 现在我收到以下错误 IndexError boolean index did not match indexed array along dimension 0 dimens
  • 在Python中将数组的元素从科学记数法转换为十进制记数法

    我有一个 numpy 数组 其元素采用科学格式 我想将它们转换为十进制格式 我的 numpy 数组如下所示 array 93495052 96955582 98555123 06146193 array 1 00097681e 09 9 9
  • 对象对于所需数组来说太深 - scipy.integrate.odeint

    我昨天刚开始使用Python 使用时遇到错误scipy integrate odeint 我定义了一个函数 def SIR x t beta gamma mu M 这需要numpy array物体x t and M 标量浮动beta gam
  • Numpy 花哨的索引和分配

    通常 numpy 会强制分配的左侧和右侧匹配 例如如果我这样做a b b必须是相同的形状或广播到相同的形状a 但该规则似乎有一个例外 gt gt gt a np arange 10 gt gt gt a array 0 1 2 3 4 5
  • 将滑块添加到 matplotlib 图表

    我有一个 matplotlib 代码 可以生成一个简单的 2D 图表 我想为 hte 和 hre 变量 它们是数组 添加滑块小部件 以便可以交互地增加或减少 hte 和 hre 值 有没有办法 我确信有 因为我已经看到了某物 http ma
  • 乘以行并按单元格值附加到数据框

    考虑以下数据框 df pd DataFrame X a b c d Y a b d e Z a b c d 1 2 1 3 df 我想在 列中附加数字大于 1 的行 并在该行中的数字减 1 df 最好应该 然后看起来像这样 或者它可能看起来
  • PyTorch DataLoader 对并行运行的批次使用相同的随机种子

    有一个bug https tanelp github io posts a bug that plagues thousands of open source ml projects 在 PyTorch Numpy 中 当并行加载批次时Da
  • 使用最新值进行采样

    考虑以下系列 created at 2014 01 27 21 50 05 040961 80000 00 2014 03 12 18 46 45 517968 79900 00 2014 09 05 20 54 17 991260 636
  • Numpy:生成二维高斯 pdf 总和作为数组

    我正在尝试生成一个 600 x 600 numpy 数组 其中包含 10 个类似高斯数组的总和 每个数组都有一个随机生成的中心 我尝试使用高斯滤波器来生成各个类似高斯的数组 然后将它们相加 但我确信有一种矢量化的方法可以解决这个问题 即使n
  • 使用 numpy 加速 for 循环

    下一个 for 循环如何使用 numpy 获得加速 我想这里可以使用一些奇特的索引技巧 但我不知道是哪一个 这里可以使用 einsum 吗 a 0 for i in range len b a numpy mean C d e f b i
  • Python:在任意维度中使用冒号运算符对数组进行索引

    我有一个 numpy nd 数组 我的任务的简化版本是沿着每个轴获取一个向量 为了显示 import numpy x numpy array range 24 reshape 2 3 4 x0 x 0 0 x1 x 0 0 x2 x 0 0
  • 重新排列 numpy 数组

    我正在尝试 就地 修改 numpy 数组 我感兴趣的是就地重新排列数组 而不是 return ing 数组的重新排列版本 这是一个示例代码 from numpy import def modar arr arr arr 1 0 commen
  • 在 Python 3.6 中,为什么负数的分数次方在 numpy 数组中返回 nan?

    我最近开始学习Python 并且经历了NumPy 官方快速入门指南 https docs scipy org doc numpy dev user quickstart html indexing slicing and iterating

随机推荐

  • 在CMD命令行模式下运行.py文件,提示:无法初始化设备PRN

    在CMD命令行模式下运行 py文件 xff0c 提示 xff1a 无法初始化设备PRN 问题的重现步骤 xff1a 首次学习python xff0c 不知道 py文件是如何创建的 xff0c 故新建了一个txt文件 xff0c 添加完内容之
  • office 2010 Word,Excel的功能区突然消失了

    office 2010 Word Excel的功能区突然消失了 xff0c 点击展开功能区无效 在网上搜了很久没有找到解决办法 Office都卸载重装过还是无法解决 在网上找到一个方法 xff1a 将com加载项的ntkofficecont
  • IndentationError:expected an indented block

    xfeff xfeff 在用python写判断语句时 xff0c 报错 错误语句写法如下 xff1a 报错信息如下 xff1a 解决方案如下 xff1a 在print前面加上Tab 问题迎刃而解
  • kindeditor使用可能遇到的问题

    1 音视频上传不能播放问题 xff08 使用自定义video标签 xff09 更改kindeditor all min js中的 mediaImg方法 function mediaImg blankPath attrs if attrs s
  • manjaro21折腾笔记

    1 换源以及更新 1 1 配置镜像源 span class token function sudo span pacman mirrors i c China m rank 输入后会出现源列表选项 xff0c 全选即可 1 2 设置源 打开
  • 最简nvim配置

    1 安装nvim span class token function sudo span span class token function apt get span span class token function install sp
  • 竟然可以在Windows下用Nvim写代码?2.nvim基础插件配置

    在windows下用nvim写代码 使用wsl和terminal简直不要太方便 保姆级教学 一篇就够了 一 下载plug 可以用指令安装 curl fLo config nvim autoload plug vim create dirs
  • vscode国内源下载

    https az764295 vo msecnd net stable ea3859d4ba2f3e577a159bc91e3074c5d85c0523 VSCodeUserSetup x64 1 52 1 exe 将官方下载地址的域名更换
  • linux下搜狗拼音隐藏悬浮状态栏

    打开配置文件 vim config sogoupinyin conf env ini 找到以下内容 并修改为0 StatusAppearance 61 0 重启fcitx状态栏就消失了 killall fcitx fcitx
  • JavaScript笔记(2)

    7 对象 xff1a 对象的三种声明与调用方法 span class token comment 第一种声明方法 span span class token keyword let span ObjectName span class to
  • C++类与对象笔记

    C 43 43 类与对象笔记 本章主要讲了面向对象三大特性 xff1a 封装 xff0c 继承 xff0c 多态 C 43 43 认为万事万物都皆为对象 xff0c 对象上有其属性和行为 例如 xff1a 人可以作为对象 xff0c 属性有
  • C++基础笔记

    C 43 43 基础笔记 本章主要讲了在c的基础上 xff0c c 43 43 的拓扑基础的部分 xff0c 还有内存的分配 1 内存分区模型 C 43 43 程序在执行时 xff0c 将内存大方向划分为4个区域 1 代码区 xff1a 存
  • linux文件名匹配(通配符使用)

    当在使用命令行时 xff0c 有很多时间都用来查找你所需要的文件 xff0c 如ls find等 S h e l l提供了一套完整的字符串模式匹配规则 xff0c 或者称之为元字符 xff0c 当s h e l l遇到上述字符时 xff0c
  • Android指纹识别,兼容Android 6.0 - Android 11

    目录 前言 概览 1 类 2 权限 详细介绍 1 BiometricManager 属性和方法 是否可用的状态码 方法 2 BiometricPrompt 属性和方法 验证的结果常用错误码 不全 方法 实战 第一步 引入支持库 第二步 检查
  • Lottie-Android详解

    Lottie是什么 Lottie是Airbnb开源的一套跨平台的 完整的动画效果解决方案 xff0c 适用于 Android iOS Web 和 Windows 平台 xff0c 它解析使用 Bodymovin 导出为 json 的 Ado
  • 组合问题,n个元素分成k组-5

    题目要求 P n k 代表将n个元素分成k个非空分组集合的总集 例如 xff0c 当L 61 1 2 3 P xff08 3 xff0c 2 xff09 61 12 3 13 2 1 23 我们就假设此n个元素是从1到n P 4 3 61
  • FTPClient踩过的坑

    一 ftpClient enterLocalPassiveMode public static final int PASSIVE LOCAL DATA CONNECTION MODE 61 2 官网关于该常量的说明 xff1a A con
  • Camera基本属性了解及设置

    将camera肯定是要有预览界面来配合着才有激情 xff0c 不然无图无真相 那就讲的没有太大的激情 我们对camera的使用一般是在app里面有用到设置获取图片的时候提供一个拍照功能 xff0c 一般是跳转到系统的拍照界面使用camera
  • 验证码不显示的解决方法

    方法一 xff1a 出现上面的情况 xff0c 最基本的一个错误就是你很可能在php里面忘记安装gd模块了 window环境下面只需要在php ini文件里面找到 把前面的分号去掉就可以了 xff0c 重启apache后 xff0c 你就可
  • 纯NumPy代码从头实现简单的卷积神经网络

    在某些情况下 xff0c 使用 ML DL 库中已经存在的模型可能会很便捷 但为了更好地控制和理解模型 xff0c 你应该自己去实现它们 本文展示了如何仅使用 NumPy 库来实现 CNN 卷积神经网络 xff08 CNN xff09 是分