深度学习 经典网络模型对比分析 LeNet / AlexNet / VGGNet / GoogLeNet / ResNet / DenseNet_resnet对lenet的优势-程序员宅基地

技术标签: pycharm  GoogLeNet  AlexNet  Python运行  经典深度学习神经网络  对比分析  VGGNet  TensorFlow  

背景:imagenet比赛自2009年开赛,到2017年截赛,催生了众多经典的深度学习神经网络模型,这也就是李飞飞教授团队对行业发展的最大贡献之一。此后的很多网络模型几乎都是基于这些经典的网络模型所衍生。

网络发展主要特点:网络加深,增强卷积模块

LeNet: 

LeNet诞生于1998年,网络结构比较完整,包括卷积层、pooling层、全连接层。被认为是CNN的鼻祖。

输入32*32*1

卷积层3个:卷积的主要目的是使原始信号特征增强,并且降低噪音  卷积核 5*5 

下采样层2个(池化):池化层的作用是降低网络训练参数及模型的过拟合程度。

全连接1个

输出层1个 10个类别 softmax 

AlexNet

2012年提出AlexNet网络8层网络结构 5conv +5pooling +3fc+1000output class

输入:224x224x3

各层神经元的数量:253,440=>186,624=>64,896=>64,896=>43,264=>4096=>4096=>1000(ImageNet有1000个类

主要优势包括:

网络加深(5个卷积层+3个全连接层+1个softmax层);

解决过拟合(dropout,data augmentation,LRN(local resonce normalization));多GPU运算。

非线性激活函数:ReLu 代替sigmoid,发现收敛SGD的收敛速度比sigmoid/tanh快很多局部响应归一化层 local response

normaliztion layer Overlapping Pooling 池化操作提取的是一小部分的代表性特征,减少冗余信息,如果stride=2 window=2 传统

池化,更改为 stride2 window3 -》overlapping pooling 有重叠部分这种池化只能稍微减轻过拟合。

传统的激活函数一般是sigmoid和tanh两种饱和非线性函数,就训练时间来说,使用这些饱和的非线性函数会比使用非饱和的非线性函数ReLU,模型收敛需要更长的时间。而对于大型的数据集来说,更快的学习过程意味着可以节省更多的时间。除此之外,ReLU也引入了一定的稀疏性,在特征表示的范畴内,数据有一定的稀疏性,也就是说,有一部分的数据其实是冗余的。通过引入ReLU,可以模拟这种稀疏性,以最大近似的方式来保留数据的特征。

减轻过拟合:数据增强,dropout ,learning rate decay 数据增强的两种方式:

(1)平移翻转,对称 从256x256的图片中随机截取224x224的部分出来;
(2) 改变rgb的通道 的强度:给图像增加一些随机的光照,彩色变化,颜色抖动。

这里的p和λ是RGB值3x3协方差矩阵的特征向量和特征值。α是均值为1标准差为0.1的高斯随机变量。

这么做的原因是利用了自然图片的一条重要性质:物体的鉴别特征并不会因为图片强度和颜色的变化而变化,也就是说,一定程度上改变图片的对比度、亮度、物体的颜色,并不会影响我们对物体的识别。在ImageNet上使用这个方法,降低了1%的top-1 error

dropout :Dropout是一种Bagging的近似
Bagging定义k个不同的模型,从training set采样出k个不同的数据集,在第i个模型上用第i个数据集进行训练,最后综合k个模型的结果,获得最终的模型。但是需要的空间、时间都很大,在DNN中并不现实。

Dropout的目的是在指数级子网络的深度神经网络中近似Bagging。也就是说,在训练时,每次Dropout后,训练的网络是整个深度神经网络的其中一个子网络。在测试时,将dropout层取消,这样得到的前向传播结果其实就是若干个子网络前向传播综合结果的一种近似。

dropout,以0.5的概率将每个隐藏神经元的输出设置为0,以这种方式被抑制的神经元既不参与前向也不参与反向传播。每次输入一个样本,相当于该神经网络尝试一个新结构,但是这些结构之间的共享权值,因为神经元不能依赖其他的神经元而存在,所以这种技术降低了神经元复杂的互适应性,因此,网络需要被迫学习更加健壮的特征,这些特征结合其他神经元的一些不同随机子集时很有用,如果没有dropout网络会出现大量的过拟合,dropout使收敛所需的迭代次数增加一倍。

learning rate decay  随着训练的进行,逐渐减小学习率 。

2012年,Imagenet比赛冠军的model——Alexnet [2](以第一作者alex命名)。caffe的model文件在这里。说实话,这个model的意义比后面那些model都大很多,首先它证明了CNN在复杂模型下的有效性,然后GPU实现使得训练在可接受的时间范围内得到结果,确实让CNN和GPU都大火了一把,顺便推动了有监督DL的发展。

模型结构见下图,别看只有寥寥八层(不算input层),但是它有60M以上的参数总量,事实上在参数量上比后面的网络都大

224*224*3 (rgb)

253,440=>186,624=>64,896=>64,896=>43,264=>4096=>4096=>1000(ImageNet有1000个类)

计算186624是怎么来的?27*27*256

一个feature map 计算 

这个图有点点特殊的地方是卷积部分都是画成上下两块,意思是说吧这一层计算出来的feature map分开,但是前一层用到的数据要看连接的虚线,如图中input层之后的第一层第二层之间的虚线是分开的,是说二层上面的128map是由一层上面的48map计算的,下面同理;而第三层前面的虚线是完全交叉的,就是说每一个192map都是由前面的128+128=256map同时计算得到的。

Alexnet有一个特殊的计算层,LRN层,做的事是对当前层的输出结果做平滑处理。下面是我画的示意图:

前后几层(对应位置的点)对中间这一层做一下平滑约束,计算方法是:

具体打开Alexnet的每一阶段(含一次卷积主要计算)来看[2][3]:

(1)con - relu - pooling - LRN

具体计算都在图里面写了,要注意的是input层是227*227,而不是paper里面·······························的224*224,这里可以算一下,主要是227可以整除后面的conv1计算,224不整除。如果一定要用224可以通过自动补边实现,不过在input就补边感觉没有意义,补得也是0。

(2)conv - relu - pool - LRN

和上面基本一样,唯独需要注意的是group=2,这个属性强行把前面结果的feature map分开,卷积部分分成两部分做。

(3)conv - relu

(4)conv-relu

(5)conv - relu - pool

(6)fc - relu - dropout

这里有一层特殊的dropout层,在alexnet中是说在训练的以1/2概率使得隐藏层的某些neuron的输出为0,这样就丢到了一半节点的输出,BP的时候也不更新这些节点。 
(7) fc - relu - dropout 

(8)fc - softmax 

VGG-Net

2014年提出VGG-Net网络,。

主要优势包括:

网络更深,使用更多的层,通常有16-19层;  kernel大小,卷积stride,

所有 卷积层用同样大小(3 x 3)的 卷积核(减少参数),核步长统一为1,padding 统一为1 。 。证明更小的卷积核并且增加卷积神经网络的深度可以有效的提高模型的性能。

直观上我们会觉得大的卷积核更好,因为它可以提取到更大区域内的信息,但是实际上,大卷积核可以用多个小卷积核进行代替。例如,一个  的卷积核就可以用两个串联的  卷积核来代替,一个  的卷积核就可以用三个串联的  卷积核来代替。这样的替代方式有几点好处:

1.减少参数,两个串联小卷积 3*3*2 =18  5*5=25 串联三个小卷积 3*3*3=27 7*7=49 。
2.引入更多的非线性:多少个串联的小卷积核就对应着多少次激活(activation)的过程,而一个大的卷积核就只有一次激活的过程。引入了更多的非线性变换,也就意味着模型的表达能力会更强,可以去拟合更高维的分布。
3.VGGNet结构的C里面还用到了  的卷积核。但是这里对这种卷积核的使用并不是像Inception里面拿来对通道进行整合,模拟升维和降维,这里并没有改变通道数,所以可以理解为是进一步的引入非线性。

GoogLeNet( Inception v1~v4, deeper):

提出Inception结构,这是NIN(Network In Network)的结构,即原来的结点也是一个网络。
googlenet[4][5],14年比赛冠军的model,这个model证明了一件事:用更多的卷积,更深的层次可以得到更好的结构。(当然,它并没有证明浅的层次不能达到这样的效果)

GoogLeNet的核心思想是:将全连接,甚至卷积中的局部连接,全部替换为稀疏连接。

既能保持网络结构的稀疏性,又能利用密集计算的高效性的方法。inception产生。

改进:

将原来线性卷积层改为多层感知卷积层
将全连接层改为全局平均池化
网络中有三个softmax,这是为了减轻在深层网络反向传播时梯度消失的影响,也就是说,整个网络的loss是由三个softmax共同组成的,这样在反向传播的时候,即使最后一个softmax传播回来的梯度消失了,还有前两个softmax传播回来的梯度进行辅助

主要思想:

深度:22层,为了避免梯度消失,巧妙在不同深度的地方增加两个损失函数避免反向传播时梯度消失的问题
宽度:1*1 3*3 5*5 结合起来的特征映射厚度将会更大,1*1卷积核降维,起降低特征映射厚度的作用。

naive inception 

这个model基本上构成部件和alexnet差不多,不过中间有好几个inception的结构:

NIN(network in network) 1*1卷积层的意义和作用:改变通道数,参数减少,提高模型的性能是说一分四,然后做一些不同大小的卷积,之后再堆叠feature map。

计算量如下图,可以看到参数总量并不大,但是计算次数是非常大的。 

ResNet

问题:增加网络深度后,网络可以进行更加复杂的特征提取,因此更深的模型可以取得更好的结果。但是,网络加深后不仅测试误差变高了,它的训练误差竟然也变高了。作者提出,这可能是因为更深的网络会伴随梯度消失/爆炸问题,从而阻碍网络的收敛。作者将这种加深网络深度但网络性能却下降的现象称为退化问题,degradation problem. 反向传导的过程中有两条线,一条如果梯度消失,另一条不消失。

解决问题:随着网络加深,网络退化的问题, 提出batch normalization 一定程度上缓解这个问题,但是仍然不足以满足需求。

提出构建恒等映射。问题解决的标志是:增加网络层数,但训练误差不增加。为什么是恒等映射呢,我是这样子想的:20层的网络是56层网络的一个子集,如果我们将56层网络的最后36层全部短接,这些层进来是什么出来也是什么(也就是做一个恒等映射),那这个56层网络不就等效于20层网络了吗,至少效果不会相比原先的20层网络差吧。那不引入恒等映射的56层网络为什么不行呢?因为梯度消失现象使得网络难以训练,虽然网络的深度加深了,但是实际上无法有效训练网络,训练不充分的网络不但无法提升性能,甚至降低了性能。

残差:观测值与估计值之间的差距 x是原来,h(x) 预测 那么f(x)=h(X)-x 残差

resnet,其实是如果能用,几层网络去逼近一个复杂的非线性映射h(x)来预测图片的分类,同样可以用这几层网络去逼近它的残差函数 F(x)=H(X)-X,并且认为优化残差映射要比直接优化H(X)简单。原来输入x 希望输出h(X) ,我们令H(x)=F(x)+x,那么我们的网络就只需要学习输出一个残差F(x)=H(x)-x。 希望用两层的weight layer的传播来拟合残差,那么我们想要得到的理想映射H(x)=F(x)+x。这就是残差网络的基本理念,网络学习的是去拟合残差,而不是直接拟合输入和输出直接的映射。

resnet网络 主要的5种变形: resnet18,res34,res50,res101,res152.

刚刚我们调用的resnet18( )函数中有一句 ResNet(BasicBlock, [2, 2, 2, 2], **kwargs),这里的[2, 2, 2, 2]与图中红框是一致的,如果你将这行代码改为 ResNet(BasicBlock, [3, 4, 6, 3], **kwargs), 那你就会得到一个res34网络。

Bottleneck结构和1*1卷积
ResNet50起,就采用Bottleneck结构,主要是引入1x1卷积。我们来看一下这里的1x1卷积有什么作用:

对通道数进行升维和降维(跨通道信息整合),实现了多个特征图的线性组合,同时保持了原有的特征图大小;

相比于其他尺寸的卷积核,可以极大地降低运算复杂度;

如果使用两个3x3卷积堆叠,只有一个relu,但使用1x1卷积就会有两个relu,引入了更多的非线性映射;

Basicblock和Bottleneck结构

我们来计算一下1*1卷积的计算量优势:首先看上图右边的bottleneck结构,对于256维的输入特征,参数数目:1x1x256x64+3x3x64x64+1x1x64x256=69632,如果同样的输入输出维度但不使用1x1卷积,而使用两个3x3卷积的话,参数数目为(3x3x256x256)x2=1179648。简单计算下就知道了,使用了1x1卷积的bottleneck将计算量简化为原有的5.9%,收益超高。

先降 后升 1*1 

ResNet的网络设计规律
整个ResNet不使用dropout,全部使用BN。此外,回到最初的这张细节图,我们不难发现一些规律和特点:

受VGG的启发,卷积层主要是3×3卷积;

对于相同的输出特征图大小的层,即同一stage,具有相同数量的3x3滤波器;

如果特征地图大小减半,滤波器的数量加倍以保持每层的时间复度。

每个stage通过步长为2的卷积层执行下采样,而却这个下采样只会在每一个satge的第一个卷积完成,有且仅有一次。

网络以全局平均池化层和softmax的1000路全连接层结束。

ResNet的常见改进
改进一:改进downsample部分,减少信息流失。前面说过了,每个stage的第一个conv都有下采样的步骤,我们看左边第一张图左侧的通路,input数据进入后在会经历一个stride=2的1*1卷积,将特征图尺寸减小为原先的一半,请注意1x1卷积和stride=2会导致输入特征图3/4的信息不被利用,因此ResNet-B的改进就是就是将下采样移到后面的3x3卷积里面去做,避免了信息的大量流失。ResNet-C则是另一种思路。ResNet-D则是在ResNet-B的基础上将identity部分的下采样交给avgpool去做,避免出现1x1卷积和stride同时出现造成信息流失。

改进二:ResNet V2。这是由ResNet原班人马打造的,主要是对ResNet部分组件的顺序进行了调整。各种魔改中常见的预激活ResNet就是出自这里。

原始的resnet是上图中的a的模式,我们可以看到相加后需要进入ReLU做一个非线性激活,这里一个改进就是砍掉了这个非线性激活,不难理解,如果将ReLU放在原先的位置,那么残差块输出永远是非负的,这制约了模型的表达能力,因此我们需要做一些调整,我们将这个ReLU移入了残差块内部,也就是图e的模式。

从模型集成角度理解ResNet的有效性
ResNet 中其实是存在着很多路径的集合,整个ResNet类似于多个网络的集成学习,证据是删除部分ResNet的网络结点,不影响整个网络的性能,但是在VGG上做同样的事请网络立刻崩溃,由此可见相比其他网络ResNet对于部分路径的缺失不敏感

从梯度反向传播角度理解ResNet的有效性
残差结构使得梯度反向传播时,更不易出现梯度消失等问题,由于Skip Connection的存在,梯度能畅通无阻地通过各个Res blocks,下面我们来推导一下 ResNet v2 的反向传播过程。

我们从这个表达式可以看出来:第l层的梯度里,包含了第L层的梯度,通俗的说就是第L层的梯度直接传递给了第l层。因为梯度消失问题主要是发生在浅层,这种将深层梯度直接传递给浅层的做法,有效缓解了深度神经网络梯度消失的问题。

 

densenet:

Dense Block,它包括输入层在内共有5层,H是BN+ReLU+3x3Conv的操作,并不改变feature map的大小。对于每一层来说,前面所有层的feature map都被直接拿来作为这一层的输入。growth rate就是除了输入层之外,每一层feature map的个数。它的目的是,使得block中的任意两层都能够直接”沟通“。
其实在Dense Block输出的地方还有一个bottleneck layer,在bottleneck layer中的操作是一个1x1的卷积,卷积核共有4k个,降低channel维度,也就是减少了模型的参数。
在transition layer中有进一步压缩的操作称为compression,减少百分之θ的feature map数量,论文中使用的θ=0.5。

 concat 依次累积上去。

DenseBlock是包含很多层的模块,每个层的特征图大小相同,层与层之间采用密集连接方式。

Transition模块是连接两个相邻的DenseBlock,并且通过Pooling使特征图大小降低。图4给出了DenseNet的网路结构,它共包含4个DenseBlock,各个DenseBlock之间通过Transition连接在一起。

然后介绍DenseNet的模型:

DenseNet其实是由若干个Dense Block串联起来而得到的,在每个Dense Block之间有一个Convolution+Pooling的操作,也就是图1中的transition layer。transition layer存在的意义是实现池化,作者在论文中承认了pooling的重要性。

分析一下为什么会从ResNet发展到DenseNet:
借用论文里的话,ResNet直接通过"Summation"操作将特征加起来,一定程度上阻碍(impede)了网络中的信息流。DenseNet通过连接(concatenate)操作来结合feature map,并且每一层都与其他层有关系,都有”沟通“,这种方式使得信息流最大化。其实DenseNet中的dense connectivity就是一种升级版的shortcut connection,提升了网络的鲁棒性并且加快了学习速度。

在DenseBlock中,各个层的特征图大小一致,可以在channel维度上连接。DenseBlock中的非线性组合函数  采用的是BN+ReLU+3x3 Conv的结构。

growth rate:
denseblock 中自己产生的k个featuremap=growth rate .然后在累积上以上的channel
另外值得注意的一点是,与ResNet不同,所有DenseBlock中各个层卷积之后均输出  个特征图,即得到的特征图的channel数为  ,或者说采用  个卷积核。  在DenseNet称为growth rate,这是一个超参数。一般情况下使用较小的  (比如12),就可以得到较佳的性能。假定输入层的特征图的channel数为  ,那么  层输入的channel数为  ,因此随着层数增加,尽管  设定得较小,DenseBlock的输入会非常多,不过这是由于特征重用所造成的,每个层仅有 个特征是自己独有的。

由于后面层的输入会非常大,DenseBlock内部可以采用bottleneck层来减少计算量,主要是原有的结构中增加1x1 Conv,如图7所示,即BN+ReLU+1x1 Conv+BN+ReLU+3x3 Conv,称为DenseNet-B结构。其中1x1 Conv得到  个特征图它起到的作用是降低特征数量,从而提升计算效率。

对于Transition层
它主要是连接两个相邻的DenseBlock,并且降低特征图大小。Transition层包括一个1x1的卷积和2x2的AvgPooling,结构为BN+ReLU+1x1 Conv+2x2 AvgPooling。另外,Transition层可以起到压缩模型的作用。假定Transition的上接DenseBlock得到的特征图channels数为  ,Transition层可以产生  个特征(通过卷积层),其中  是压缩系数(compression rate)。当  时,特征个数经过Transition层没有变化,即无压缩,而当压缩系数小于1时,这种结构称为DenseNet-C,文中使用  。对于使用bottleneck层的DenseBlock结构和压缩系数小于1的Transition组合结构称为DenseNet-BC

 
实验结果:
DenseNet共在三个图像分类数据集(CIFAR,SVHN和ImageNet)上进行测试。对于前两个数据集,其输入图片大小为  ,所使用的DenseNet在进入第一个DenseBlock之前,首先进行进行一次3x3卷积(stride=1),卷积核数为16(对于DenseNet-BC为  )。DenseNet共包含三个DenseBlock,各个模块的特征图大小分别为  ,  和  ,每个DenseBlock里面的层数相同。最后的DenseBlock之后是一个global AvgPooling层,然后送入一个softmax分类器。注意,在DenseNet中,所有的3x3卷积均采用padding=1的方式以保证特征图大小维持不变。对于基本的DenseNet,使用如下三种网络配置:  ,  ,  。而对于DenseNet-BC结构,使用如下三种网络配置:  ,  ,  。这里的  指的是网络总层数(网络深度),一般情况下,我们只把带有训练参数的层算入其中,而像Pooling这样的无参数层不纳入统计中,此外BN层尽管包含参数但是也不单独统计,而是可以计入它所附属的卷积层。对于普通的  网络,除去第一个卷积层、2个Transition中卷积层以及最后的Linear层,共剩余36层,均分到三个DenseBlock可知每个DenseBlock包含12层。其它的网络配置同样可以算出各个DenseBlock所含层数。

DenseNet的各种模型结构:
对于ImageNet数据集,图片输入大小为  ,网络结构采用包含4个DenseBlock的DenseNet-BC,其首先是一个stride=2的7x7卷积层(卷积核数为  ),然后是一个stride=2的3x3 MaxPooling层,后面才进入DenseBlock。

 
--------------------- 
原文:https://blog.csdn.net/weixin_41108334/article/details/83827332

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wills798/article/details/89365554

智能推荐

python编码问题之encode、decode、codecs模块_python中encode在什么模块-程序员宅基地

文章浏览阅读2.1k次。原文链接先说说编解码问题编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。 Eg:str1.decode('gb2312') #将gb2312编码的字符串转换成unicode编码str2.encode('gb2312') #将unicode编码..._python中encode在什么模块

Java数据流-程序员宅基地

文章浏览阅读949次,点赞21次,收藏15次。本文介绍了Java中的数据输入流(DataInputStream)和数据输出流(DataOutputStream)的使用方法。

ie浏览器无法兼容的问题汇总_ie 浏览器 newdate-程序员宅基地

文章浏览阅读111次。ie无法兼容_ie 浏览器 newdate

想用K8s,还得先会Docker吗?其实完全没必要-程序员宅基地

文章浏览阅读239次。这篇文章把 Docker 和 K8s 的关系给大家做了一个解答,希望还在迟疑自己现有的知识储备能不能直接学 K8s 的,赶紧行动起来,K8s 是典型的入门有点难,后面越用越香。

ADI中文手册获取方法_adi 如何查看数据手册-程序员宅基地

文章浏览阅读561次。ADI中文手册获取方法_adi 如何查看数据手册

React 分页-程序员宅基地

文章浏览阅读1k次,点赞4次,收藏3次。React 获取接口数据实现分页效果以拼多多接口为例实现思路加载前 加载动画加载后 判断有内容的时候 无内容的时候用到的知识点1、动画效果(用在加载前,加载之后就隐藏或关闭,用开关效果即可)2、axios请求3、map渲染页面4、分页插件(antd)代码实现import React, { Component } from 'react';//引入axiosimport axios from 'axios';//引入antd插件import { Pagination }_react 分页

随便推点

关于使用CryPtopp库进行RSA签名与验签的一些说明_cryptopp 签名-程序员宅基地

文章浏览阅读449次,点赞9次,收藏7次。这个变量与验签过程中的SignatureVerificationFilter::PUT_MESSAGE这个宏是对应的,SignatureVerificationFilter::PUT_MESSAGE,如果在签名过程中putMessage设置为true,则在验签过程中需要添加SignatureVerificationFilter::PUT_MESSAGE。项目中使用到了CryPtopp库进行RSA签名与验签,但是在使用过程中反复提示无效的数字签名。否则就会出现文章开头出现的数字签名无效。_cryptopp 签名

新闻稿的写作格式_新闻稿时间应该放在什么位置-程序员宅基地

文章浏览阅读848次。新闻稿是新闻从业者经常使用的一种文体,它的格式与内容都有着一定的规范。本文将从新闻稿的格式和范文两个方面进行介绍,以帮助读者更好地了解新闻稿的写作_新闻稿时间应该放在什么位置

Java中的转换器设计模式_java转换器模式-程序员宅基地

文章浏览阅读1.7k次。Java中的转换器设计模式 在这篇文章中,我们将讨论 Java / J2EE项目中最常用的 Converter Design Pattern。由于Java8 功能不仅提供了相应类型之间的通用双向转换方式,而且还提供了转换相同类型对象集合的常用方法,从而将样板代码减少到绝对最小值。我们使用Java8 功能编写了..._java转换器模式

应用k8s入门-程序员宅基地

文章浏览阅读150次。1,kubectl run创建pods[root@master ~]# kubectl run nginx-deploy --image=nginx:1.14-alpine --port=80 --replicas=1[root@master ~]# kubectl get podsNAME READY STATUS REST...

PAT菜鸡进化史_乙级_1003_1003 pat乙级 最优-程序员宅基地

文章浏览阅读128次。PAT菜鸡进化史_乙级_1003“答案正确”是自动判题系统给出的最令人欢喜的回复。本题属于 PAT 的“答案正确”大派送 —— 只要读入的字符串满足下列条件,系统就输出“答案正确”,否则输出“答案错误”。得到“答案正确”的条件是: 1. 字符串中必须仅有 P、 A、 T这三种字符,不可以包含其它字符; 2. 任意形如 xPATx 的字符串都可以获得“答案正确”,其中 x 或者是空字符串,或..._1003 pat乙级 最优

CH340与Android串口通信_340串口小板 安卓给安卓发指令-程序员宅基地

文章浏览阅读5.6k次。CH340与Android串口通信为何要将CH340的ATD+Eclipse上的安卓工程移植到AndroidStudio移植的具体步骤CH340串口通信驱动函数通信过程中重难点还存在的问题为何要将CH340的ATD+Eclipse上的安卓工程移植到AndroidStudio为了在这个工程基础上进行改动,验证串口的数据和配置串口的参数,我首先在Eclipse上配置了安卓开发环境,注意在配置环境是..._340串口小板 安卓给安卓发指令