5-2 Pytorch中的模型层layers

深度学习模型一般由各种模型层组合而成。
torch.nn中内置了非常丰富的各种模型层。它们都属于nn.Module的子类,具备参数管理功能。
例如:
nn.Linear, nn.Flatten, nn.Dropout, nn.BatchNorm2d, nn.Embedding
nn.Conv2d,nn.AvgPool2d,nn.Conv1d,nn.ConvTranspose2d
nn.GRU,nn.LSTM
nn.Transformer
如果这些内置模型层不能够满足需求,我们也可以通过继承nn.Module基类构建自定义的模型层。
实际上,pytorch不区分模型和模型层,都是通过继承nn.Module进行构建。
因此,我们只要继承nn.Module基类并实现forward方法即可自定义模型层。

一、基础层

一些基础的内置模型层简单介绍如下。

  • nn.Linear:全连接层。参数个数 = 输入层特征数× 输出层特征数(weight)+ 输出层特征数(bias)
  • nn.Embedding:嵌入层。一种比Onehot更加有效的对离散特征进行编码的方法。**一般用于将输入中的单词映射为稠密向量。**嵌入层的参数需要学习。
  • nn.Flatten:压平层,用于将多维张量样本压成一维张量样本。
  • nn.BatchNorm1d:一维批标准化层。通过线性变换将输入批次缩放平移到稳定的均值和标准差。可以增强模型对输入不同分布的适应性,加快模型训练速度,有轻微正则化效果。一般在激活函数之前使用。可以用afine参数设置该层是否含有可以训练的参数。
  • nn.BatchNorm2d:二维批标准化层。 常用于CV领域。
  • nn.BatchNorm3d:三维批标准化层。
  • nn.Dropout:一维随机丢弃层。一种正则化手段
  • nn.Dropout2d:二维随机丢弃层。
  • nn.Dropout3d:三维随机丢弃层。
  • nn.Threshold:限幅层。当输入大于或小于阈值范围时,截断之。
  • nn.ConstantPad2d: 二维常数填充层。对二维张量样本填充常数扩展长度。
  • nn.ReplicationPad1d: 一维复制填充层。对一维张量样本通过复制边缘值填充扩展长度。
  • nn.ZeroPad2d:二维零值填充层。对二维张量样本在边缘填充0值.
  • nn.GroupNorm:组归一化。一种替代批归一化的方法,将通道分成若干组进行归一。不受batch大小限制。
  • nn.LayerNorm:层归一化。常用于NLP领域,不受序列长度不一致影响。
  • nn.InstanceNorm2d: 样本归一化。一般在图像风格迁移任务中效果较好。

重点说说各种归一化层:
image.png
结构化数据的BatchNorm1D归一化 【结构化数据的主要区分度来自每个样本特征在全体样本中的排序,将全部样本的某个特征都进行相同的放大缩小平移操作,样本间的区分度基本保持不变,所以结构化数据可以做BatchNorm,但LayerNorm会打乱全体样本根据某个特征的排序关系,引起区分度下降】

图片数据的各种归一化(一般常用BatchNorm2D)【图片数据的主要区分度来自图片中的纹理结构,所以图片数据的归一化一定要在图片的宽高方向上操作以保持纹理结构,此外在Batch维度上操作还能够引入少许的正则化,对提升精度有进一步的帮助。】

文本数据的LayerNorm归一化 【文本数据的主要区分度来自于词向量(Embedding向量)的方向,所以文本数据的归一化一定要在 特征(通道)维度上操作 以保持 词向量方向不变。此外文本数据还有一个重要的特点是不同样本的序列长度往往不一样,所以不可以在Sequence和Batch维度上做归一化,否则将不可避免地让padding位置对应的向量变成非零向量】

此外,有论文提出了一种可自适应学习的归一化:SwitchableNorm,可应用于各种场景且有一定的效果提升。【SwitchableNorm是将BN、LN、IN结合,赋予权重,让网络自己去学习归一化层应该使用什么方法。】论文链接
对BatchNorm需要注意的几点:
(1)BatchNorm放在激活函数前还是激活函数后?
原始论文认为将BatchNorm放在激活函数前效果较好,后面的研究一般认为将BatchNorm放在激活函数之后更好。
(2)BatchNorm在训练过程和推理过程的逻辑是否一样?
不一样!训练过程BatchNorm的均值和方差和根据mini-batch中的数据估计的,而推理过程中BatchNorm的均值和方差是用的训练过程中的全体样本估计的。因此预测过程是稳定的,相同的样本不会因为所在批次的差异得到不同的结果,但训练过程中则会受到批次中其他样本的影响所以有正则化效果。
(3)BatchNorm的精度效果与batch_size大小有何关系?
如果受到GPU内存限制,不得不使用很小的batch_size,训练阶段时使用的mini-batch上的均值和方差的估计和预测阶段时使用的全体样本上的均值和方差的估计差异可能会较大,效果会变差。这时候,可以尝试LayerNorm或者GroupNorm等归一化方法。

nn.BatchNorm2d:

import torch 
from torch import nn batch_size, channel, height, width = 32, 16, 128, 128tensor = torch.arange(0,32*16*128*128).view(32,16,128,128).float() bn = nn.BatchNorm2d(num_features=channel,affine=False)
bn_out = bn(tensor)channel_mean = torch.mean(bn_out[:,0,:,:]) 
channel_std = torch.std(bn_out[:,0,:,:])
print("channel mean:",channel_mean.item())
print("channel std:",channel_std.item())

image.png
nn.LayerNorm:

import torch 
from torch import nn batch_size, sequence, features = 32, 100, 2048
tensor = torch.arange(0,32*100*2048).view(32,100,2048).float() ln = nn.LayerNorm(normalized_shape=[features],elementwise_affine = False)ln_out = ln(tensor)token_mean = torch.mean(ln_out[0,0,:]) 
token_std = torch.std(ln_out[0,0,:])
print("token_mean:",token_mean.item())
print("token_mean:",token_std.item())

image.png

二、卷积网络相关层

一些与卷积相关的内置层介绍如下:
nn.Conv1d:普通一维卷积,常用于文本。参数个数 = 输入通道数×卷积核尺寸(如3)×卷积核个数 + 卷积核尺寸(如3)=卷积核尺寸(如3乘3)x输出通道数+输出通道数(偏置数量)
nn.Conv2d:普通二维卷积,常用于图像。参数个数 = 输入通道数×卷积核尺寸(如3乘3)×卷积核个数 + 卷积核尺寸(如3乘3)。=卷积核尺寸(如3乘3)x输入通道数x输出通道数+输出通道数(偏置数量)) 通过调整dilation参数大于1,可以变成空洞卷积,增加感受野。 通过调整groups参数不为1,可以变成分组卷积。分组卷积中每个卷积核仅对其对应的一个分组进行操作。 当groups参数数量等于输入通道数时,相当于tensorflow中的二维深度卷积层tf.keras.layers.DepthwiseConv2D。 利用分组卷积和1乘1卷积的组合操作,可以构造相当于Keras中的二维深度可分离卷积层tf.keras.layers.SeparableConv2D。
nn.Conv3d:普通三维卷积,常用于视频。参数个数 = 输入通道数×卷积核尺寸(如3乘3乘3)×卷积核个数 + 卷积核尺寸(如3乘3乘3) 。
nn.MaxPool1d: 一维最大池化。
nn.MaxPool2d:二维最大池化。一种下采样方式。没有需要训练的参数。
nn.MaxPool3d:三维最大池化。
nn.AdaptiveMaxPool2d:二维自适应最大池化。无论输入图像的尺寸如何变化,输出的图像尺寸是固定的。 该函数的实现原理,大概是通过输入图像的尺寸和要得到的输出图像的尺寸来反向推算池化算子的padding,stride等参数。
nn.FractionalMaxPool2d:二维分数最大池化。普通最大池化通常输入尺寸是输出的整数倍。而分数最大池化则可以不必是整数。分数最大池化使用了一些随机采样策略,有一定的正则效果,可以用它来代替普通最大池化和Dropout层。
nn.AvgPool2d:二维平均池化。
nn.AdaptiveAvgPool2d:二维自适应平均池化。无论输入的维度如何变化,输出的维度是固定的。
nn.ConvTranspose2d:二维卷积转置层,俗称反卷积层。并非卷积的逆操作,但在卷积核相同的情况下,当其输入尺寸是卷积操作输出尺寸的情况下,卷积转置的输出尺寸恰好是卷积操作的输入尺寸。在语义分割中可用于上采样。
nn.Upsample:上采样层,操作效果和池化相反。可以通过mode参数控制上采样策略为"nearest"最邻近策略或"linear"线性插值策略。
nn.Unfold:滑动窗口提取层。其参数和卷积操作nn.Conv2d相同。实际上,卷积操作可以等价于nn.Unfold和nn.Linear以及nn.Fold的一个组合。 其中nn.Unfold操作可以从输入中提取各个滑动窗口的数值矩阵,并将其压平成一维。利用nn.Linear将nn.Unfold的输出和卷积核做乘法后,再使用 nn.Fold操作将结果转换成输出图片形状。
nn.Fold:逆滑动窗口提取层。

重点说说各种常用的卷积层和上采样层:
普通卷积【普通卷积的操作分成3个维度,在空间维度(H和W维度)是共享卷积核权重滑窗相乘求和(融合空间信息),在输入通道维度是每一个通道使用不同的卷积核参数并对输入通道维度求和(融合通道信息),在输出通道维度操作方式是并行堆叠(多种),有多少个卷积核就有多少个输出通道】

空洞卷积【和普通卷积相比,空洞卷积可以在保持较小参数规模的条件下增大感受野,常用于图像分割领域。其缺点是可能产生网格效应,即有些像素被空洞漏过无法利用到,可以通过使用不同膨胀因子的空洞卷积的组合来克服该问题。

分组卷积 【和普通卷积相比,分组卷积将输入通道分成g组,卷积核也分成对应的g组,每个卷积核只在其对应的那组输入通道上做卷积,最后将g组结果堆叠拼接。由于每个卷积核只需要在全部输入通道的1/g个通道上做卷积,参数量降低为普通卷积的1/g。分组卷积要求输入通道和输出通道数都是g的整数倍。

深度可分离卷积【深度可分离卷积的思想是先用g=m(输入通道数)的分组卷积逐通道作用融合空间信息,再用n(输出通道数)个1乘1卷积融合通道信息。 其参数量为 (m×k×k)+ n×m, 相比普通卷积的参数量 m×n×k×k 显著减小 】。

转置卷积 【一般的卷积操作后会让特征图尺寸变小,但转置卷积(也被称为反卷积)可以实现相反的效果,即放大特征图尺寸。对两种方式理解转置卷积,第一种方式是转置卷积是一种特殊的卷积,通过设置合适的padding的大小来恢复特征图尺寸。第二种理解基于卷积运算的矩阵乘法表示方法,转置卷积相当于将卷积核对应的表示矩阵做转置,然后乘上输出特征图压平的一维向量,即可恢复原始输入特征图的大小。

上采样层 【除了使用转置卷积进行上采样外,在图像分割领域更多的时候一般是使用双线性插值的方式进行上采样,该方法没有需要学习的参数,通常效果也更好,除了双线性插值之外,还可以使用最邻近插值的方式进行上采样,但使用较少。】

import torch 
from torch import nn 
import torch.nn.functional as F # 卷积输出尺寸计算公式 o = (i + 2*p -k')//s  + 1 
# 对空洞卷积 k' = d(k-1) + 1
# o是输出尺寸,i 是输入尺寸,p是 padding大小, k 是卷积核尺寸, s是stride步长, d是dilation空洞参数inputs = torch.arange(0,25).view(1,1,5,5).float() # i= 5
filters = torch.tensor([[[[1.0,1],[1,1]]]]) # k = 2outputs = F.conv2d(inputs, filters) # o = (5+2*0-2)//1+1 = 4
outputs_s2 = F.conv2d(inputs, filters, stride=2)  #o = (5+2*0-2)//2+1 = 2
outputs_p1 = F.conv2d(inputs, filters, padding=1) #o = (5+2*1-2)//1+1 = 6
outputs_d2 = F.conv2d(inputs,filters, dilation=2) #o = (5+2*0-(2(2-1)+1))//1+1 = 3print("--inputs--")
print(inputs)
print("--filters--")
print(filters)print("--outputs--")
print(outputs,"\n")print("--outputs(stride=2)--")
print(outputs_s2,"\n")print("--outputs(padding=1)--")
print(outputs_p1,"\n")print("--outputs(dilation=2)--")
print(outputs_d2,"\n")

image.png
image.png

import torch 
from torch import nn features = torch.randn(8,64,128,128)
print("features.shape:",features.shape)
print("\n")#普通卷积
print("--conv--")
conv = nn.Conv2d(in_channels=64,out_channels=32,kernel_size=3)
conv_out = conv(features)
print("conv_out.shape:",conv_out.shape) 
print("conv.weight.shape:",conv.weight.shape)
print("\n")#分组卷积
print("--group conv--")
conv_group = nn.Conv2d(in_channels=64,out_channels=32,kernel_size=3,groups=8)
group_out = conv_group(features)
print("group_out.shape:",group_out.shape) 
print("conv_group.weight.shape:",conv_group.weight.shape)
print("\n")#深度可分离卷积
print("--separable conv--")
depth_conv = nn.Conv2d(in_channels=64,out_channels=64,kernel_size=3,groups=64)
oneone_conv = nn.Conv2d(in_channels=64,out_channels=32,kernel_size=1)
separable_conv = nn.Sequential(depth_conv,oneone_conv)
separable_out = separable_conv(features)
print("separable_out.shape:",separable_out.shape) 
print("depth_conv.weight.shape:",depth_conv.weight.shape)
print("oneone_conv.weight.shape:",oneone_conv.weight.shape)
print("\n")#转置卷积
print("--conv transpose--")
conv_t = nn.ConvTranspose2d(in_channels=32,out_channels=64,kernel_size=3)
features_like = conv_t(conv_out)
print("features_like.shape:",features_like.shape)
print("conv_t.weight.shape:",conv_t.weight.shape)

image.png

import torch 
from torch import nn inputs = torch.arange(1, 5, dtype=torch.float32).view(1, 1, 2, 2)
print("inputs:")
print(inputs)
print("\n")
# 上采样
nearest = nn.Upsample(scale_factor=2, mode='nearest')
bilinear = nn.Upsample(scale_factor=2,mode="bilinear",align_corners=True)print("nearest(inputs):")
print(nearest(inputs))
print("\n")
print("bilinear(inputs):")
print(bilinear(inputs)) 

image.png

三、循环网络相关层

nn.LSTM:长短记忆循环网络层【支持多层】。最普遍使用的循环网络层。具有携带轨道,遗忘门,更新门,输出门。可以较为有效地缓解梯度消失问题,从而能够适用长期依赖问题。设置bidirectional = True时可以得到双向LSTM。需要注意的时,默认的输入和输出形状是(seq,batch,feature), 如果需要将batch维度放在第0维,则要设置batch_first参数设置为True。
nn.GRU:门控循环网络层【支持多层】。LSTM的低配版,不具有携带轨道,参数数量少于LSTM,训练速度更快。
nn.RNN:简单循环网络层【支持多层】。容易存在梯度消失,不能够适用长期依赖问题。一般较少使用。
nn.LSTMCell:长短记忆循环网络单元。和nn.LSTM在整个序列上迭代相比,它仅在序列上迭代一步。一般较少使用。
nn.GRUCell:门控循环网络单元。和nn.GRU在整个序列上迭代相比,它仅在序列上迭代一步。一般较少使用。
nn.RNNCell:简单循环网络单元。和nn.RNN在整个序列上迭代相比,它仅在序列上迭代一步。一般较少使用。
一般地,各种RNN序列模型层(RNN,GRU,LSTM等)可以用函数表示如下:
image.png
这个公式的含义是:t时刻循环神经网络的输出向量ℎ𝑡由t-1时刻的输出向量ℎ𝑡−1和t时刻的输入𝑖𝑡变换而来。

  • LSTM结构解析:

LSTM通过引入了三个门来控制信息的传递,分别是遗忘门,输入门 和输出门 。三个门的作用为:
(1)遗忘门: 遗忘门𝑓𝑡控制上一时刻的内部状态 需要遗忘多少信息;
(2)输入门: 输入门𝑖𝑡控制当前时刻的候选状态 有多少信息需要保存;
(3)输出门: 输出门𝑜𝑡控制当前时刻的内部状态 有多少信息需要输出给外部状态 ;
image.png

  • GRU 结构解析:

GRU的结构比LSTM更为简单一些,GRU只有两个门,更新门和重置门 。
(1)更新门:更新门用于控制每一步ℎ𝑡被更新的比例,更新门越大,ℎ𝑡更新幅度越大。
(2)重置门:重置门用于控制更新候选向量ℎ̃ 𝑡中前一步的状态ℎ𝑡−1被重新放入的比例,重置门越大,更新候选向量中ℎ𝑡−1被重新放进来的比例越大。
公式中的小圈表示哈达玛积,也就是两个向量逐位相乘。
其中(1)式和(2)式计算的是更新门𝑢𝑡和重置门𝑟𝑡,是两个长度和ℎ𝑡相同的向量。
注意到(4)式 实际上和ResNet的残差结构是相似的,都是 f(x) = x + g(x) 的形式,可以有效地防止长序列学习反向传播过程中梯度消失问题。
image.png
GRU的参数数量为LSTM的3/4。

import torch 
from torch import nn inputs = torch.randn(8,200,64) #batch_size, seq_length, featuresgru = nn.GRU(input_size=64,hidden_size=32,num_layers=1,batch_first=True)
gru_output,gru_hn = gru(inputs)
print("--GRU--")
print("gru_output.shape:",gru_output.shape)
print("gru_hn.shape:",gru_hn.shape)
print("\n")print("--LSTM--")
lstm = nn.LSTM(input_size=64,hidden_size=32,num_layers=1,batch_first=True)
lstm_output,(lstm_hn,lstm_cn) = lstm(inputs)
print("lstm_output.shape:",lstm_output.shape)
print("lstm_hn.shape:",lstm_hn.shape)
print("lstm_cn.shape:",lstm_cn.shape)

image.png
image.png
image.png
参考:https://github.com/lyhue1991/eat_pytorch_in_20_days

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/81080.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

layui框架学习(45: 工具集模块)

layui的工具集模块util支持固定条、倒计时等组件,同时提供辅助函数处理时间数据、字符转义、批量事件处理等操作。   util模块中的fixbar函数支持设置固定条(2.7版本的帮助文档中叫固定块),是指固定在页面一侧的工具条元素&…

小程序引入vant-Weapp保姆级教程及安装过程的问题解决

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。 本文同时参与 「掘力星计划」,赢取创作大礼包,挑战创作激励金 当你想在小程序里引入vant时,第一步:打开官方文档,第二步&#xff…

RK3399平台开发系列讲解(入门篇)VIM的基础命令

🚀返回专栏总目录 文章目录 一、Vim 命令速查二、其他命令三、Vim模式沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 本篇将介绍Vim相关命令。 一、Vim 命令速查 简单说明一下,这张图上展示了一个键盘。图中的“•”表示,单个字母不是完整的命令,必须再有进一步…

elasticsearch5-RestAPI操作

个人名片: 博主:酒徒ᝰ. 个人简介:沉醉在酒中,借着一股酒劲,去拼搏一个未来。 本篇励志:三人行,必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》,SpringCloud…

typeScript 类型推论

什么是类型推论? 类型推论是 TypeScript 中的一个特性,它允许开发人员不必显式地指定变量的类型。相反,开发人员可以根据变量的使用情况让 TypeScript 编译器自动推断出类型。例如,如果开发人员将一个字符串赋值给一个变量&#…

【大数据】Neo4j 图数据库使用详解

目录 一、图数据库介绍 1.1 什么是图数据库 1.2 为什么需要图数据库 1.3 图数据库应用领域 二、图数据库Neo4j简介 2.1 Neo4j特性 2.2 Neo4j优点 三、Neo4j数据模型 3.1 图论基础 3.2 属性图模型 3.3 Neo4j的构建元素 3.3.1 节点 3.3.2 属性 3.3.3 关系 3.3.4 标…

智囊AI-基于 ChatGPT 的 AI 工具产品 你的私人AI助手

智囊AI是一款基于 ChatGPT 的 AI 工具产品,主打免费、智能、方便,可以在此雇佣各种各样的免费智囊进行对话、自己创造和分享智囊、共享有趣有用的对话等。不过使用需要注册登录,可以使用自己的openai key或者使用网站提供的api key&#xff0…

常见的API

常见的 API Math 从 JDK 版本 1 开始的, 用来计算的一些方法 这里面定义了两个常量的 PI 和 E 这两个是最接近 pi 的值和最接近对数的值 Abs (int a ) 取绝对值Ceil (double a)向上取整Floor (double a )向下取整Round (float a)四舍五入Max (int a, int b) 取最大值Pow (dou…

yarn的资源优化的调整参数

yarn的资源优化的调整参数 官网: https://hadoop.apache.org/docs/r3.3.6/hadoop-yarn/hadoop-yarn-common/yarn-default.xml 没事多看官网哈 yarn.nodemanager.resource.memory-mb:用于设置NodeManager节点的总内存容量,单位为MB。根据集…

PostgreSQL缓存管理

缓冲区管理器、存储和后端进程之间的关系 缓存管理结构 PostgreSQL 缓冲区管理器由buffer table、buffer descriptors和buffer pool组成。buffer pool层存储表和索引等数据文件页,以及空闲空间映射和可见性映射。buffer pool是一个数组,每个槽存储数据文…

TensorFlow与pytorch特定版本虚拟环境的安装

TensorFlow与Python的版本对应,注意,一定要选择对应的版本,否则会让你非常痛苦,折腾很久搞不清楚原因。 建议使用国内镜像源安装 没有GPU后缀的就表示是CPU版本的,不加版本就是最新 pip install tensorflow -i https:…

150.逆波兰表达式求值

目录 一、题目 二、分析代码 三、中缀表达式转后缀表达式 一、题目 150. 逆波兰表达式求值 - 力扣&#xff08;LeetCode&#xff09; 二、分析代码 class Solution { public:int evalRPN(vector<string>& tokens) {stack<int>s;for(auto ch:tokens){if(ch!…

车载软件架构 —— AUTOSAR Vector SIP包(一)

车载软件架构 —— AUTOSAR Vector SIP包(一) 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人生在…

进程程序替换

✅<1>主页&#xff1a;&#xff1a;我的代码爱吃辣 &#x1f4c3;<2>知识讲解&#xff1a;Linux——进程替换 ☂️<3>开发环境&#xff1a;Centos7 &#x1f4ac;<4>前言&#xff1a;我们创建子进程的目的是什么&#xff1f;想让子进程帮我们执行特定的…

Docker搭建ELK日志采集服务及Kibana可视化图表展示

架构 ES docker network create elkmkdir -p /opt/ELK/es/datachmod 777 /opt/ELK/esdocker run -d --name elasticsearch --net elk -p 9200:9200 -p 9300:9300 -e "discovery.typesingle-node" -v /opt/ELK/es/plugins:/usr/share/elasticsearch/plugins -v /opt/…

嵌入式C 语言中的三块技术难点

​ C 语言在嵌入式学习中是必备的知识&#xff0c;甚至大部分操作系统都要围绕 C 语言进行&#xff0c;而其中有三块技术难点&#xff0c;几乎是公认级别的“难啃的硬骨头”。 今天就来带你将这三块硬骨头细细拆解开来&#xff0c;一定让你看明白了。 0x01 指针 指针是公认…

redis实战-redis实现异步秒杀优化

秒杀优化-异步秒杀思路 未优化的思路 当用户发起请求&#xff0c;此时会请求nginx&#xff0c;nginx会访问到tomcat&#xff0c;而tomcat中的程序&#xff0c;会进行串行操作&#xff0c;分成如下几个步骤 1、查询优惠卷 2、判断秒杀库存是否足够 3、查询订单 4、校验是否是一…

MySQL——主从复制

简介 在实际的生产中&#xff0c;为了解决Mysql的单点故障已经提高MySQL的整体服务性能&#xff0c;一般都会采用「主从复制」。 主从复制开始前有个前提条件&#xff1a;两边的数据要一样&#xff0c;主必须开启二进制日志 dump thread 线程 基于位置点从是否需要开启二进…

计算机组成原理——基础入门总结(一)

本帖更新一些关于计算机组成原理的重点内容。由于博主考研时并不会考这门课&#xff0c;但是考虑到操作系统中又很多重要晦涩的概念涉及很多诸如内存、存储器、磁盘、cpu乃至各种寄存器的知识&#xff0c;此处挑选一些核心的内容总结复盘一遍——实现声明&#xff1a;本帖的内容…

Python统计pdf中英文单词的个数

之前的文章提供了批量识别pdf中英文的方法,详见【python爬虫】批量识别pdf中的英文,自动翻译成中文上。以及自动pdf英文转中文文档,详见【python爬虫】批量识别pdf中的英文,自动翻译成中文下。    本文实现python统计pdf中英文字符的个数。 文章目录 一、要统计字符的pdf…