当前位置: 首页 > news >正文

CNN简介与实现

CNN简介与实现

  • 导语
  • 整体结构
  • 卷积层
    • 卷积
    • 填充
    • 步幅
    • 三维卷积
      • 立体化
      • 批处理
    • 实现
  • 池化层
    • 特点
    • 实现
  • CNN实现
  • 可视化
  • 总结
  • 参考文献

导语

CNN全称卷积神经网络,可谓声名远扬,被用于生活中的各个领域,也是最好理解的神经网络结构之一。

整体结构

相较于先前的神经网络,CNN出现了卷积层和池化层的概念,基本的组成模块是“卷积-ReLU-池化”,并且,在靠近输出或最后输出时时仍会采用“Affine-ReLU”、"Affine-ReLU"的组合,书上给出的示例图如下:

在这里插入图片描述

卷积层

在思考为什么要用卷积层之前,我们可以先来看看卷积层之前的全连接层有什么局限性,全连接层通常要求输入是一个一维的数组,即使原始数据是更高维的数据,如高、长、通道的三维图像,这个时候,使用全连接层,原始数据中的几何信息、点之间的相对位置等空间信息就都被清除了,这些信息其实很重要,因为点与点之间在高维空间的关联性是比一维更强的。

相比之下,卷积层就考虑到了这些空间信息,当输入为图像时,卷积层会以三维数据的形式接受输入数据,并且输出也是三维数据。

CNN中卷积层的输入输出数据被称作特征图,输入叫输入特征图,输出叫输出特征图。

卷积

卷积是卷积层的运算,类似与图像中的滤波器处理,具体做法如图(图源自网络,侵删):

在这里插入图片描述

此图省略了卷积核,只给出了输入和结果,以该图为例,输入是一个4×4的矩阵,在矩阵上存在一个3×3的滑动窗口,窗口每次移动一个单位,每次对窗口内的矩阵A进行一次权重累和,具体的权重为同等大小的卷积核矩阵,具体的例子如下, 36 = 1 × 1 + 2 × 1 + 0 × 3 + 4 × 0 + 5 × 2 + 6 × 0 + 7 × 1 + 8 × 2 + 1 × 1 36=1×1+2×1+0×3+4×0+5×2+6×0+7×1+8×2+1×1 36=1×1+2×1+0×3+4×0+5×2+6×0+7×1+8×2+1×1

在这里插入图片描述

与全连接层一样,CNN中也存在偏置,对于算出的结果矩阵,对矩阵中的所有元素可以加上一个相同的偏置值。

填充

在进行卷积前,有时候要把数据拓宽,例如把4×4拓成6×6,如何拓宽呢很简单,把不够的部分都设置为同一个值就可以(一般是0或者1),具体操作如图(图源网络,侵删):

在这里插入图片描述

这种做法,就叫做填充,使用填充主要是为了调整输出大小,在使用卷积核运算的时候,如果不进行填充,卷积的结果势必会在整体上变小(如4×4变成2×2),多次使用后,最后的结果就可能只有一个1,因此使用填充来避免这种情况的发生。

步幅

步幅很容易理解,就是滑动窗口的每次的移动距离,像下面这张图,就是步幅为2时候的卷积(图源网络,侵删):

在这里插入图片描述
可以看到,增大步幅会使得输出变小,加上填充会变大,这个时候就可以根据两者关系列出卷积输出结果的公式了。

书上的描述如下(值除不尽四舍五入):

在这里插入图片描述

三维卷积

在现实使用中,CNN的输入并不是一个单纯的二维矩阵,输入的图像时一个带有高、宽、通道的具体的特征图,以RGB为例,RGB图像是三通道,如果对RGB图像进行卷积,那么就要对图像上的每一个通道都使用一个卷积核,通道方向有多个特征图时,需要按照通道方向进行输入数据和滤波器的卷积运算,并将结果累和,生成一个新的二维矩阵。

立体化

当我们把输入和输出推向更一般的适用情况,多通道输入数据使用对应的多通道核,最后输出一张单个图,书上的例子如下,其中C为通道数、H为高度、W为长度。

在这里插入图片描述

如果要再通道方向上也拥有多个卷积运算的输出,就需要使用多个滤波器(权重),书上的图如下:

在这里插入图片描述

如果再考虑上偏置,书上给出的图如下:

在这里插入图片描述

批处理

通常,为了加快效率,神经网络会将输入数据进行一批批的打包,一次性处理一堆数据,为了处理一批数据,需要在上一张图的基础上加上批次,书上给出的图如下:

在这里插入图片描述

数据作为4维数据在各层之间传递,批处理将N次处理汇总成了1次进行。

实现

如果直接实现卷积运算,利用for循环,效率其实是不高的,况且python给出了更好的选择:im2col函数。

im2col将输入数据展开来适合卷积核的计算,书上给出的图如下:

在这里插入图片描述

这里更详细的解释一下,输入的是一个三维的数据,把每一面(二维)从左到右,从上到下,拉成一个一维的数组,然后把每个通道的一维数组拼起来,形成一个二维的矩阵,如果是多批次,就把这些矩阵首尾相连,形成一个更大的二维矩阵即可。

实际的卷积运算中,卷积核的应用区域几乎彼此重叠,因此,在使用im2col之后,展开的元素个数会多于原来的输入元素个数,所以会消耗更多的内存。

书上给出了用im2col进行卷积的流程:
在这里插入图片描述
还需要明晰的一点是,im2col的使用并不会损失原数据在空间上的信息,它只是为了方便进行矩阵对数据进行了一些处理,并且在最后恢复了原来的数据模式。

书上给出了im2col和基于im2col实现的卷积层代码如下:

def im2col(input_data, filter_h, filter_w, stride=1, pad=0):#输入,高,长,步幅,填充N, C, H, W = input_data.shapeout_h = (H + 2*pad - filter_h)//stride + 1#根据步长和高度计算输出的长高out_w = (W + 2*pad - filter_w)//stride + 1img = np.pad(input_data, [(0,0), (0,0), (pad, pad), (pad, pad)], 'constant')col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))#设置一个空的拉伸之后的二维数组for y in range(filter_h):y_max = y + stride*out_hfor x in range(filter_w):x_max = x + stride*out_wcol[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N*out_h*out_w, -1)return colClass Convolution:def __init__(self,W,b,stride=1,pad=0):#初始化赋值self.W=Wself.b=bself.stride=strideself.pad=paddef forward(self,x):FN,C,FH,FW=self.W.shapeN,C,H,W=x.shapeout_h=int(1+(H+2*self.pad-FH)/self.stride)#获得填充和卷积之后的规模out_w=int(1+(W+2*self.pad-FW)/self.stride)col=im2col(x,FH,FW,self.stride,self.pad)#拉伸#卷积层反向传播的时候,需要进行im2col的逆处理col_W=self.W.reshape(FN,-1).T#把卷积核展开out=np.dot(col,col_W)+self.bout=out.reshape(N,out_h,out_w,-1).transpose(0,3,1,2)#更改轴的顺序,NHWC变成NCHWreturn outdef backward(self, dout):FN, C, FH, FW = self.W.shapedout = dout.transpose(0,2,3,1).reshape(-1, FN)self.db = np.sum(dout, axis=0)self.dW = np.dot(self.col.T, dout)self.dW = self.dW.transpose(1, 0).reshape(FN, C, FH, FW)dcol = np.dot(dout, self.col_W.T)dx = col2im(dcol, self.x.shape, FH, FW, self.stride, self.pad)#逆运算return dx

池化层

简单来说,卷积是使用卷积核计算对应区域的乘积和,池化层是选取对应区域的最大值(也有其他的池化,比如平均值池化,指的是取对应区域的平均值作为输出),书上给出的例子如下:

在这里插入图片描述

特点

池化层的操作很简单,不需要像卷积层那样学习卷积核的参数,只需要提取最值或平均即可;其次,池化层的计算是按照通道独立进行的,输入和输出的通道数不会变化;最后,池化层对输入数据的微小偏差具有鲁棒性(例如目标区域的非最大值有变化,并不会影响池化层最后的输出)。

实现

池化层也是用im2col展开,但展开时在通道方向上是独立的,书上给的图示如下:

在这里插入图片描述

书上的实现代码如下:

class Pooling:def __init__(self, pool_h, pool_w, stride=1, pad=0):#初始化self.pool_h = pool_hself.pool_w = pool_wself.stride = strideself.pad = padself.x = Noneself.arg_max = Nonedef forward(self, x):#推理函数N, C, H, W = x.shapeout_h = int(1 + (H - self.pool_h) / self.stride)#拿到输出大小out_w = int(1 + (W - self.pool_w) / self.stride)col = im2col(x, self.pool_h, self.pool_w, self.stride, self.pad)#拉伸col = col.reshape(-1, self.pool_h*self.pool_w)#变成二维矩阵arg_max = np.argmax(col, axis=1)out = np.max(col, axis=1)#取最值out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)#还原成数据self.x = xself.arg_max = arg_maxreturn outdef backward(self, dout):#反向传播dout = dout.transpose(0, 2, 3, 1)pool_size = self.pool_h * self.pool_wdmax = np.zeros((dout.size, pool_size))dmax[np.arange(self.arg_max.size), self.arg_max.flatten()] = dout.flatten()dmax = dmax.reshape(dout.shape + (pool_size,)) dcol = dmax.reshape(dmax.shape[0] * dmax.shape[1] * dmax.shape[2], -1)dx = col2im(dcol, self.x.shape, self.pool_h, self.pool_w, self.stride, self.pad)return dx

CNN实现

将已经实现的各个层进行组合,就可以实现一个简单的CNN,书上给出了一个简单CNN的具体代码实现,具体图如下:
在这里插入图片描述

书上加上注释的代码如下:

class SimpleConvNet:def __init__(self, input_dim=(1, 28, 28), conv_param={'filter_num':30, 'filter_size':5, 'pad':0, 'stride':1},hidden_size=100, output_size=10, weight_init_std=0.01):#输入大小,卷积核数量,卷积核大小,填充,步幅,隐藏层神经元数量,输出大小,初始权重标准差filter_num = conv_param['filter_num']filter_size = conv_param['filter_size']filter_pad = conv_param['pad']filter_stride = conv_param['stride']input_size = input_dim[1]conv_output_size = (input_size - filter_size + 2*filter_pad) / filter_stride + 1pool_output_size = int(filter_num * (conv_output_size/2) * (conv_output_size/2))# 初始化权重self.params = {}self.params['W1'] = weight_init_std * \np.random.randn(filter_num, input_dim[0], filter_size, filter_size)self.params['b1'] = np.zeros(filter_num)self.params['W2'] = weight_init_std * \np.random.randn(pool_output_size, hidden_size)self.params['b2'] = np.zeros(hidden_size)self.params['W3'] = weight_init_std * \np.random.randn(hidden_size, output_size)self.params['b3'] = np.zeros(output_size)# 生成层self.layers = OrderedDict()self.layers['Conv1'] = Convolution(self.params['W1'], self.params['b1'],conv_param['stride'], conv_param['pad'])self.layers['Relu1'] = Relu()self.layers['Pool1'] = Pooling(pool_h=2, pool_w=2, stride=2)self.layers['Affine1'] = Affine(self.params['W2'], self.params['b2'])self.layers['Relu2'] = Relu()self.layers['Affine2'] = Affine(self.params['W3'], self.params['b3'])self.last_layer = SoftmaxWithLoss()#损失函数def predict(self, x):#预测值for layer in self.layers.values():x = layer.forward(x)return xdef loss(self, x, t):#计算损失y = self.predict(x)return self.last_layer.forward(y, t)def accuracy(self, x, t, batch_size=100):#计算准确度if t.ndim != 1 : t = np.argmax(t, axis=1)acc = 0.0for i in range(int(x.shape[0] / batch_size)):tx = x[i*batch_size:(i+1)*batch_size]tt = t[i*batch_size:(i+1)*batch_size]y = self.predict(tx)y = np.argmax(y, axis=1)acc += np.sum(y == tt) return acc / x.shape[0]def numerical_gradient(self, x, t):#求梯度,用数值微分方法loss_w = lambda w: self.loss(x, t)grads = {}for idx in (1, 2, 3):grads['W' + str(idx)] = numerical_gradient(loss_w, self.params['W' + str(idx)])grads['b' + str(idx)] = numerical_gradient(loss_w, self.params['b' + str(idx)])return gradsdef gradient(self, x, t):#误差反向传播求梯度# forwardself.loss(x, t)# backwarddout = 1dout = self.last_layer.backward(dout)layers = list(self.layers.values())layers.reverse()for layer in layers:dout = layer.backward(dout)# 设定grads = {}grads['W1'], grads['b1'] = self.layers['Conv1'].dW, self.layers['Conv1'].dbgrads['W2'], grads['b2'] = self.layers['Affine1'].dW, self.layers['Affine1'].dbgrads['W3'], grads['b3'] = self.layers['Affine2'].dW, self.layers['Affine2'].dbreturn grads

训练所需要的时间相较于先前的方法比较久,但是得到的结果识别率更高,具体训练结果如下:

在这里插入图片描述在这里插入图片描述

可视化

“卷积”是一种数学运算,逻辑上其实很难理解到它的用处,因此,书上给出了对卷积作用更加直接的展现方式,以上一部分学习前和学习后的卷积核为例,各个卷积核的权重图如下:

学习前:

在这里插入图片描述
学习后:

在这里插入图片描述

可以明显的看到,学习前杂乱无章的权重矩阵,在学习后变得有迹可循,明显有些区域的权重更深一些,那么,这些权重更大的部分对应的目标究竟是什么呢?

书上给出了答案:这些卷积核在学习边缘(颜色变化的分界线)和斑块(局部的块状区域),例如黑白分界线,可以根据手写数字识别的例子想象,手写的数字是黑色,背景是白色,那么卷积核的目标就是使得模型对黑色的部分更加敏感,权重更大。

上述的结果是只进行了一次卷积得到的,随着层次的加深,提取的信息也会越来越抽象,在深度学习中,最开始层会对简单的边缘有响应,接下来是对纹理,在接下来是对更复杂的性质,随着层次递增,模型的目标会从简单的形状进化到更高级的信息。

总结

本章详细介绍了CNN的构造,对卷积层、池化层进行了从零开始的实现,但是对反向传播的部分只给出了代码实现。最重要的还是对im2col的理解,明白了im2col的原理,卷积层、池化层乃至反向传播的实现,这些问题就迎刃而解了。

基于最基本的CNN,后续还有更多功能强大,网络结构更深的CNN网络,如LeNet(激活函数为sigmod,使用子采样缩小中间数据大小,而不是卷积、池化)还有AlexNet(多个卷积层和池化层,激活函数为sigmod,使用进行局部正规化的LRN层,使用Dropout)等。

参考文献

  1. 【Pytorch实现】——深入理解im2col(详细图解)
  2. 12张动图帮你看懂卷积神经网络到底是什么
  3. 《深度学习入门——基于Python的理论与实现》

相关文章:

CNN简介与实现

CNN简介与实现 导语整体结构卷积层卷积填充步幅三维卷积立体化批处理 实现 池化层特点实现 CNN实现可视化总结参考文献 导语 CNN全称卷积神经网络,可谓声名远扬,被用于生活中的各个领域,也是最好理解的神经网络结构之一。 整体结构 相较于…...

【AI大模型】Transformers大模型库(五):AutoModel、Model Head及查看模型结构

目录​​​​​​​ 一、引言 二、自动模型类(AutoModel) 2.1 概述 2.2 Model Head(模型头) 2.3 代码示例 三、总结 一、引言 这里的Transformers指的是huggingface开发的大模型库,为huggingface上数以万计的预…...

Hadoop yixing(移行),新增表字段,删除表字段,修改存储格式

Hadoop yixing(移行),新增表字段,删除表字段,修改存储格式 一、hadoop中修改存储格式,比如从 textfile 转化为 orc 格式,表中的数据的组织形式要重新改变,就要将重新创建新格式的表将原来的数据按照新的格…...

使用汇编和proteus实现仿真数码管显示电路

proteus介绍: proteus是一个十分便捷的用于电路仿真的软件,可以用于实现电路的设计、仿真、调试等。并且可以在对应的代码编辑区域,使用代码实现电路功能的仿真。 汇编语言介绍: 百度百科介绍如下: 汇编语言是培养…...

【Unity】官方文档学习-光照系统

目录 1 前言 2 光照介绍 2.1 直接光与间接光 2.2 实时光照与烘焙光照 2.3 全局光照 3 光源 3.1 Directional Light 3.1.1 Color 3.1.2 Mode 3.1.3 Intensity 3.1.4 Indirect Multiplier 3.1.5 Shadow Type 3.1.6 Baked Shadow Angle 3.1.7 Realtime Shadows 3.1…...

1731. 每位经理的下属员工数量

1731. 每位经理的下属员工数量 题目链接:1731. 每位经理的下属员工数量 代码如下: # Write your MySQL query statement below select a.employee_id as employee_id,a.name as name,count(b.employee_id) as reports_count,round(avg(b.age),0) as av…...

特征筛选LASSO回归封装好的代码、数据集和结果

Gitee仓库地址:特征筛选LASSO回归封装好的代码、数据集和结果 README LassoFeatureSelector_main 这个是主函数文件,在实例化LassoFeatureSelector类时,需要传入下面这些参数: input_train_data_path:输入训练集的路…...

Autosar 通讯栈配置-手动配置PDU及Signal-基于ETAS软件

文章目录 前言System配置ISignalSystem SignalPduFrameISignal到System Signal的mapSystem Signal到Pdu的mapPdu到Frame的mapSignal配置Can配置CanHwFilterEcuC配置PduR配置CanIf配置CanIfInitCfgCanIfRxPduCfgCom配置ComIPduComISignalSWC配置Data mappingRTE接口Com配置补充总…...

Web前端工资调整:深入剖析与全面解读

Web前端工资调整:深入剖析与全面解读 在快速发展的互联网行业中,Web前端技术日新月异,而与之紧密相关的工资调整也成为了业内热议的话题。本文将从四个方面、五个方面、六个方面和七个方面,深入剖析Web前端工资调整的原因、趋势、…...

cesium已知两个点 写一个简单具有动画尾迹效果的抛物线

// 定义起点和终点的经纬度和高度 var start { longitude: 111.09683723811149, latitude: 38.92112250636146, elevation: 603.5831692856873 }; var end { longitude: 111.09769465526689, latitude: 38.92815375977821, elevation: 627.0132157062261 }; // 生成更多的中…...

C#中使用Mysql批量新增数据 MySqlBulkCopy

在C#中使用MySqlBulkCopy类来批量复制数据到MySQL数据库,首先需要确保你的项目中已经引用了MySQL Connector。以下是使用MySqlBulkCopy的基本步骤: 1.安装MySQL Connector。 可以通过NuGet安装MySQL Connector: 2.在代码中引用必要的命名空间…...

ARM-V9 RME(Realm Management Extension)系统架构之系统安全能力的架构差异

安全之安全(security)博客目录导读 RME系统中的应用处理单元(PE)之间的架构差异可能会带来潜在的安全风险并增加管理软件的复杂性。例如,通过在ID_AA64MMFR0_EL1.PARange中为每个PE设置不同的值来支持不同的物理范围,可能会妨碍内…...

Ansible——stat模块

目录 参数总结 返回值 基础语法 常见的命令行示例 示例1:检查文件是否存在 示例2:获取文件详细信息 示例3:检查目录是否存在 示例4:获取文件的 MD5 校验和 示例5:获取文件的 MIME 类型 高级使用 示例6&…...

第二十节:带你梳理Vue2:Vue子组件向父组件传参(事件传参)

1. 自定义事件 除了可以处理原生的DOM事件, v-on指令也可以处理组件内部触发的自定义的事件,调用this.$emit()函数就可以触发一个自定义事件 $emit() 触发事件函数接受一个自定义事件的事件名以及其他任何给事件函数传递的参数. 然后就可以在组件上使用v-on来绑定这个自定义事…...

华为od-C卷100分题目 - 10寻找最富裕的小家庭

华为od-C卷100分题目 - 10寻找最富裕的小家庭 题目描述 在一棵树中,每个节点代表一个家庭成员,节点的数字表示其个人的财富值,一个节点及其直接相连的子节点被定义为一个小家庭。 现给你一棵树,请计算出最富裕的小家庭的财富和。…...

本地部署AI大模型 —— Ollama文档中文翻译

写在前面 来自Ollama GitHub项目的README.md 文档。文档中涉及的其它文档未翻译,但是对于本地部署大模型而言足够了。 Ollama 开始使用大模型。 macOS Download Windows 预览版 Download Linux curl -fsSL https://ollama.com/install.sh | sh手动安装说明 …...

【前端技术】 ES6 介绍及常用语法说明

😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~ 🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 🎐 个人CSND主页——Mi…...

程序员具备的职业素养(个人见解)

程序员应该有什么职业素养? 1. 技术能力 毫无疑问,优秀的技术是程序员的必备。 -扎实的编程基础:熟练掌握至少一门编程语言,并理解基本的数据结构和算法,要做到精通!。 - 广泛的技术知识:了…...

Springboot 开发-- 集成 Activiti 7 流程引擎

引言 Activiti 7是一款遵循BPMN 2.0标准的开源工作流引擎,旨在为企业提供灵活、可扩展的流程管理功能。它支持图形化的流程设计、丰富的API接口、强大的执行引擎和完善的监控报表,帮助企业实现业务流程的自动化、规范化和智能化。本文将为您详细介绍 Ac…...

一些常用的frida脚本

这里整理一些常用的frida脚本,和ghidra 一起食用风味更佳~ Trace RegisterNatives 注意到从java到c的绑定中,可能会在JNI_OnLoad动态的执行RegisterNatives方法来绑定java层的函数到c行数,可以通过这个方法,来吧运行…...

计算机二级Access操作题总结——简单应用

查询设计 创建一个查询,能够在客人每次结账时根据客人的姓名提示统计这个客人已住天数和应交金额,并显示“姓名”、“房间号”、“已住天数”和“应交金额”,所建查询命名为“qT2”。 注:输入姓名时应提示“请输入姓名”。已住天…...

C#操作MySQL从入门到精通(21)——删除数据

前言: 谈到数据库,大家最容易脱口而出的就是增删改查,本文就是来详细介绍如何删除数据。 本文测试使用的数据库如下: 1、删除部分数据 使用delete 关键字,并且搭配where条件使用,否则会导致表中数据全部被删除 string sql = string.Empty;if (radioButton_DeletePart…...

【iOS】JSONModel源码阅读笔记

文章目录 前言一、JSONModel使用二、JSONModel其他方法转换属性名称 三、源码分析- (instancetype)initWithDictionary:(NSDictionary*)dict error:(NSError **)err[self init]__setup____inspectProperties - (BOOL)__doesDictionary:(NSDictionary*)dict matchModelWithKeyMa…...

如何离线下载 Microsoft Corporation II Windows Subsystem for Android

在本文中,我们将指导您通过一个便捷的步骤来离线下载 Microsoft Corporation II Windows Subsystem for Android。这个过程将利用第三方工具来生成直接下载链接,从而让您能够获取该应用程序的安装包,即使在没有访问Microsoft Store的情况下也…...

使用 flask + qwen 实现 txt2sql 流式输出

前言 一般的大模型提供的 api 都是在提问之后过很久才会返回对话内容,可能要耗时在 3 秒以上了,如果是复杂的问题,大模型在理解和推理的耗时会更长,这种展示结果的方式对于用户体验是很差的。 其实大模型也是可以进行流式输出&a…...

植物大战僵尸杂交版最新2.0.88手机+电脑+苹果+修改器

在这个充满奇妙的平行宇宙中,植物和僵尸竟然能够和谐共存!是的,你没听错!一次意外的实验,让这两个看似对立的生物种类发生了基因杂交,创造出了全新的生物种类——它们既能够进行光合作用,也具备…...

Vite - 开发初体验,以及按需导入配置

目录 开始 创建一个 Vite 项目 项目结构 /src/main.js index.html package.json vite.config.js Vite 项目中使用 vue-router Vite 组件的“按需引入” 传统的方式引入一个组件 传统方式引入带来的问题 解决办法(配置 按需引入 插件) 示例&…...

推荐云盘哪个好,各有各的优势

选择合适的云盘服务是确保数据安全、便捷分享和高效协作的关键。下面将从多个维度对目前主流的云盘服务进行详细的对比和分析: 速度性能 百度网盘青春版:根据测试,其上传和下载确实不限速,但主要定位是办公人群,适用于…...

面试题之webpack与vite系列

今天继续来分享面试题,今天要分享的技术是webpack和vite的一些区别,下面我列举了最常见的关于webpack和vite的面试题,主要有以下几个: 1.说说你对webpack的理解?plugin和loader有什么区别? Webpack是一个…...

单调队列 加 二分

雾粉与最小值(简单版) 链接: 牛客 思路 题意是 给定我们数组a让我们完成{x,l,r}询问,判断是否在a中存在子数组满足长度在l,r之间且子数组最小值大于等于x,输出yes 或者 on 一个数组,长度越长,其最小值越小&#xff…...

绍兴网站建设哪家好/平台广告推广

返璞归真这几天项目有一个linux下部署数据库的操作,数据库使用python进行初始化安装。然后问题来了,由于linux服务器涉及安全要求,除了代码以来的Python3.6版本外不允许安装其他插件与工具,不巧的是python的代码报错了…如果放在平…...

精通网站建设 100/seo搜索引擎优化就业前景

我不喜欢被当今互联网产业吹嘘到比冥王哈迪斯还该死的所谓业务逻辑,我只喜欢机器本身,所以我不会编程,是的,这是报应。 我只会C语言和汇编,但是并不很。 但我觉得C语言编译器自动生成的那些push RBP之类的指令简直糟…...

网站的二级目录是什么/汕头seo排名

1.安装依赖(内网环境 挂载光盘)本文链接原创: 我照着此文部署 yum -y install gcc gcc-c autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel glibc glibc-devel glib2 gli…...

普陀区网站开发/外包公司为什么没人去

今天做图像旋转练习的时候,要根据鼠标的移动轨迹来确定转过的角度,于是就很自然的想到通过三个点来确定这个转过的角度:图像的中心,鼠标按下的点,鼠标拖到的点。想到使用斜率来计算角度,于是联想到数学公式…...

公司网站设计很好的/网络营销工具包括

浑浑噩噩已经走了这么长时间了,那么,留下点什么吧。 一种积累,一种出口。 转载于:https://www.cnblogs.com/Peong/p/10438157.html...

自做装逼头像网站/关键词推广优化app

TCP主动关闭连接 appl: close(), --> FIN FIN_WAIT_1 //主动关闭socket方&#xff0c;调用close关闭socket,发FIN <-- ACK FIN_WAIT_2 //对方操作系统的TCP层&#xff0c;给ACK响应。然后给FIN <-- FIN …...