ResNet50卷积神经网络输出数据形参分析-笔记

ResNet50卷积神经网络输出数据形参分析-笔记

ResNet50包含多个模块,其中第2到第5个模块分别包含3、4、6、3个残差块
50=49个卷积(3+4+6+3)*3+1和一个全连接层
分析结果为:
输入数据形状:[10, 3, 224, 224]
最后输出结果:linear_0 [10, 1] [2048, 1] [1]

在这里插入图片描述
ResNet50包含多个模块,其中第2到第5个模块分别包含3、4、6、3个残差块
第1模块:7X7(64) 一个卷积
第2模块:3X3(64) 三个残差块=9个卷积
第3模块:3X3(128) 四个残差块=12个卷积
第4模块:3X3(256) 六个残差块=18个卷积
第5模块:3X3(512) 三个残差块=9个卷积
最后一个全连接层
在这里插入图片描述

分析详细过程如下所示:

PS E:\project\python> & D:/ProgramData/Anaconda3/python.exe e:/project/python/PM/ResNet_PM_test.py
layers= 50
W0804 20:41:04.044713 18388 gpu_resources.cc:61] Please NOTE: device: 0, GPU Compute Capability: 6.1, Driver API Version: 12.2, Runtime API Version: 10.2
W0804 20:41:04.053730 18388 gpu_resources.cc:91] device: 0, cuDNN Version: 7.6.
block= 0 depth[block]= 3    Cout=256 
bottleneck[ 256 64 False
bottleneck[ 256 64 True
bottleneck[ 256 64 True
create bnb 3
block= 1 depth[block]= 4   Cout=512 
bottleneck[ 512 128 False
bottleneck[ 512 128 True
bottleneck[ 512 128 True
bottleneck[ 512 128 True
create bnb 4
block= 2 depth[block]= 6   Cout=1024 
bottleneck[ 1024 256 False
bottleneck[ 1024 256 True
bottleneck[ 1024 256 True
bottleneck[ 1024 256 True
bottleneck[ 1024 256 True
bottleneck[ 1024 256 True
create bnb 6
block= 3 depth[block]= 3   Cout=2048
bottleneck[ 2048 512 False
bottleneck[ 2048 512 True
bottleneck[ 2048 512 True
create bnb 3
[10, 3, 224, 224]
conv2d_0 [10, 64, 112, 112] [64, 3, 7, 7] [ 64 ]
D:\ProgramData\Anaconda3\lib\site-packages\paddle\nn\layer\norm.py:712: UserWarning: When training, we now always track global mean and variance.warnings.warn(
conv_bn_layer_0 [10, 64, 112, 112]
maxpool2d: [10, 64, 56, 56]
======start bottleneckBlock:
#第二个模块 Cout=256  包括三个残差块bottleneckBlock
-----print bottleneckBlock: 0
conv2d_1 [10, 64, 56, 56] [64, 64, 1, 1] [ 64 ]
conv2d_2 [10, 64, 56, 56] [64, 64, 3, 3] [ 64 ]
conv2d_3 [10, 256, 56, 56] [256, 64, 1, 1] [ 256 ]
conv2d_4 [10, 256, 56, 56] [256, 64, 1, 1] [ 256 ]
end block: [10, 256, 56, 56]
-----print bottleneckBlock: 1
conv2d_5 [10, 64, 56, 56] [64, 256, 1, 1] [ 64 ]
conv2d_6 [10, 64, 56, 56] [64, 64, 3, 3] [ 64 ]
conv2d_7 [10, 256, 56, 56] [256, 64, 1, 1] [ 256 ]
end block: [10, 256, 56, 56]
-----print bottleneckBlock: 2
conv2d_8 [10, 64, 56, 56] [64, 256, 1, 1] [ 64 ]
conv2d_9 [10, 64, 56, 56] [64, 64, 3, 3] [ 64 ]
conv2d_10 [10, 256, 56, 56] [256, 64, 1, 1] [ 256 ]
end block: [10, 256, 56, 56]
#第三个模块 Cout=512  包括四个残差块bottleneckBlock
-----print bottleneckBlock: 3
conv2d_11 [10, 128, 56, 56] [128, 256, 1, 1] [ 128 ]
conv2d_12 [10, 128, 28, 28] [128, 128, 3, 3] [ 128 ]
conv2d_13 [10, 512, 28, 28] [512, 128, 1, 1] [ 512 ]
conv2d_14 [10, 512, 28, 28] [512, 256, 1, 1] [ 512 ]
end block: [10, 512, 28, 28]
-----print bottleneckBlock: 4
conv2d_15 [10, 128, 28, 28] [128, 512, 1, 1] [ 128 ]
conv2d_16 [10, 128, 28, 28] [128, 128, 3, 3] [ 128 ]
conv2d_17 [10, 512, 28, 28] [512, 128, 1, 1] [ 512 ]
end block: [10, 512, 28, 28]
-----print bottleneckBlock: 5
conv2d_18 [10, 128, 28, 28] [128, 512, 1, 1] [ 128 ]
conv2d_19 [10, 128, 28, 28] [128, 128, 3, 3] [ 128 ]
conv2d_20 [10, 512, 28, 28] [512, 128, 1, 1] [ 512 ]
end block: [10, 512, 28, 28]
-----print bottleneckBlock: 6
conv2d_21 [10, 128, 28, 28] [128, 512, 1, 1] [ 128 ]
conv2d_22 [10, 128, 28, 28] [128, 128, 3, 3] [ 128 ]
conv2d_23 [10, 512, 28, 28] [512, 128, 1, 1] [ 512 ]
end block: [10, 512, 28, 28]
#第四个模块 Cout=1024  包括六个残差块bottleneckBlock
-----print bottleneckBlock: 7
conv2d_24 [10, 256, 28, 28] [256, 512, 1, 1] [ 256 ]
conv2d_25 [10, 256, 14, 14] [256, 256, 3, 3] [ 256 ]
conv2d_26 [10, 1024, 14, 14] [1024, 256, 1, 1] [ 1024 ]
conv2d_27 [10, 1024, 14, 14] [1024, 512, 1, 1] [ 1024 ]
end block: [10, 1024, 14, 14]
-----print bottleneckBlock: 8
conv2d_28 [10, 256, 14, 14] [256, 1024, 1, 1] [ 256 ]
conv2d_29 [10, 256, 14, 14] [256, 256, 3, 3] [ 256 ]
conv2d_30 [10, 1024, 14, 14] [1024, 256, 1, 1] [ 1024 ]
end block: [10, 1024, 14, 14]
-----print bottleneckBlock: 9
conv2d_31 [10, 256, 14, 14] [256, 1024, 1, 1] [ 256 ]
conv2d_32 [10, 256, 14, 14] [256, 256, 3, 3] [ 256 ]
conv2d_33 [10, 1024, 14, 14] [1024, 256, 1, 1] [ 1024 ]
end block: [10, 1024, 14, 14]
-----print bottleneckBlock: 10
conv2d_34 [10, 256, 14, 14] [256, 1024, 1, 1] [ 256 ]
conv2d_35 [10, 256, 14, 14] [256, 256, 3, 3] [ 256 ]
conv2d_36 [10, 1024, 14, 14] [1024, 256, 1, 1] [ 1024 ]
end block: [10, 1024, 14, 14]
-----print bottleneckBlock: 11
conv2d_37 [10, 256, 14, 14] [256, 1024, 1, 1] [ 256 ]
conv2d_38 [10, 256, 14, 14] [256, 256, 3, 3] [ 256 ]
conv2d_39 [10, 1024, 14, 14] [1024, 256, 1, 1] [ 1024 ]
end block: [10, 1024, 14, 14]
-----print bottleneckBlock: 12
conv2d_40 [10, 256, 14, 14] [256, 1024, 1, 1] [ 256 ]
conv2d_41 [10, 256, 14, 14] [256, 256, 3, 3] [ 256 ]
conv2d_42 [10, 1024, 14, 14] [1024, 256, 1, 1] [ 1024 ]
end block: [10, 1024, 14, 14]
#第五个模块 Cout=2048  包括三个残差块bottleneckBlock
-----print bottleneckBlock: 13
conv2d_43 [10, 512, 14, 14] [512, 1024, 1, 1] [ 512 ]
conv2d_44 [10, 512, 7, 7] [512, 512, 3, 3] [ 512 ]
conv2d_45 [10, 2048, 7, 7] [2048, 512, 1, 1] [ 2048 ]
conv2d_46 [10, 2048, 7, 7] [2048, 1024, 1, 1] [ 2048 ]
end block: [10, 2048, 7, 7]
-----print bottleneckBlock: 14
conv2d_47 [10, 512, 7, 7] [512, 2048, 1, 1] [ 512 ]
conv2d_48 [10, 512, 7, 7] [512, 512, 3, 3] [ 512 ]
conv2d_49 [10, 2048, 7, 7] [2048, 512, 1, 1] [ 2048 ]
end block: [10, 2048, 7, 7]
-----print bottleneckBlock: 15
conv2d_50 [10, 512, 7, 7] [512, 2048, 1, 1] [ 512 ]
conv2d_51 [10, 512, 7, 7] [512, 512, 3, 3] [ 512 ]
conv2d_52 [10, 2048, 7, 7] [2048, 512, 1, 1] [ 2048 ]
end block: [10, 2048, 7, 7]
======end bottleneckBlock:
adaptive_avg_pool2d_0 [10, 2048, 1, 1]
y.shape= [10, 2048]
linear_0 [10, 1] [2048, 1] [1]
PS E:\project\python> 

分析测试代码如下所示:

# -*- coding:utf-8 -*-# ResNet模型代码
import numpy as np
import paddle
import paddle.nn as nn
import paddle.nn.functional as Fdef printItem(item,x):# item是CNN类中的一个子层# 查看经过子层之后的输出数据形状try:x = item(x)except:x = paddle.reshape(x, [x.shape[0], -1])x = item(x)  #print(len(item.parameters()))         if len(item.parameters())==1:       print(item.full_name(), x.shape,item.parameters()[0].shape,'[',item.parameters()[0].shape[0],']') #print(item)elif len(item.parameters())==2:# 查看卷积和全连接层的数据和参数的形状,# 其中item.parameters()[0]是权重参数w,item.parameters()[1]是偏置参数bprint(item.full_name(), x.shape, item.parameters()[0].shape, item.parameters()[1].shape)else:# 池化层没有参数print(item.full_name(), x.shape) return x;      # ResNet中使用了BatchNorm层,在卷积层的后面加上BatchNorm以提升数值稳定性
# 定义卷积批归一化块  (包括一个卷积)
class ConvBNLayer(paddle.nn.Layer):def __init__(self,num_channels,num_filters,filter_size,stride=1,groups=1,act=None):"""num_channels, 卷积层的输入通道数num_filters, 卷积层的输出通道数stride, 卷积层的步幅groups, 分组卷积的组数,默认groups=1不使用分组卷积"""super(ConvBNLayer, self).__init__()# 创建卷积层self._conv = nn.Conv2D(in_channels=num_channels,out_channels=num_filters,kernel_size=filter_size,stride=stride,padding=(filter_size - 1) // 2,groups=groups,bias_attr=False)# 创建BatchNorm层self._batch_norm = paddle.nn.BatchNorm2D(num_filters)self.act = actdef forward_old(self, inputs):y = self._conv(inputs)y = self._batch_norm(y)if self.act == 'leaky':y = F.leaky_relu(x=y, negative_slope=0.1)elif self.act == 'relu':y = F.relu(x=y)return ydef forward(self, inputs):y=printItem(self._conv,inputs)#print('[',num_filters,num_channels,filter_size,filter_size)y = self._batch_norm(y)if self.act == 'leaky':y = F.leaky_relu(x=y, negative_slope=0.1)elif self.act == 'relu':y = F.relu(x=y)return y# 定义残差块  (包括三个卷积)   16*3=48
# 每个残差块会对输入图片做三次卷积,然后跟输入图片进行短接
# 如果残差块中第三次卷积输出特征图的形状与输入不一致,则对输入图片做1x1卷积,将其输出形状调整成一致
class BottleneckBlock(paddle.nn.Layer):def __init__(self,num_channels,num_filters,stride,shortcut=True):super(BottleneckBlock, self).__init__()# 创建第一个卷积层 1x1self.conv0 = ConvBNLayer(num_channels=num_channels,num_filters=num_filters,filter_size=1,act='relu')# 创建第二个卷积层 3x3self.conv1 = ConvBNLayer(num_channels=num_filters,num_filters=num_filters,filter_size=3,stride=stride,act='relu')# 创建第三个卷积 1x1,但输出通道数乘以4self.conv2 = ConvBNLayer(num_channels=num_filters,num_filters=num_filters * 4,filter_size=1,act=None)# 如果conv2的输出跟此残差块的输入数据形状一致,则shortcut=True# 否则shortcut = False,添加1个1x1的卷积作用在输入数据上,使其形状变成跟conv2一致if not shortcut:self.short = ConvBNLayer(num_channels=num_channels,num_filters=num_filters * 4,filter_size=1,stride=stride)self.shortcut = shortcutself._num_channels_out = num_filters * 4def forward_old(self, inputs):y = self.conv0(inputs)conv1 = self.conv1(y)conv2 = self.conv2(conv1)# 如果shortcut=True,直接将inputs跟conv2的输出相加# 否则需要对inputs进行一次卷积,将形状调整成跟conv2输出一致if self.shortcut:short = inputselse:short = self.short(inputs)y = paddle.add(x=short, y=conv2)y = F.relu(y)return ydef forward(self, inputs): y = self.conv0(inputs)#print('>>>>ConvBMLayer0.shape=',y.shape,self.conv0)conv1 = self.conv1(y)#print('>>>>ConvBMLayer1.shape=',conv1.shape)conv2 = self.conv2(conv1)#print('>>>>ConvBMLayer2.shape=',conv2.shape)# 如果shortcut=True,直接将inputs跟conv2的输出相加# 否则需要对inputs进行一次卷积,将形状调整成跟conv2输出一致if self.shortcut:short = inputselse:short = self.short(inputs)y = paddle.add(x=short, y=conv2)y = F.relu(y)return y   # 定义ResNet模型
class ResNet(paddle.nn.Layer):def __init__(self, layers=50, class_dim=1):print('layers=',layers)"""layers, 网络层数,可以是50, 101或者152class_dim,分类标签的类别数"""super(ResNet, self).__init__()self.layers = layerssupported_layers = [50, 101, 152]assert layers in supported_layers, \"supported layers are {} but input layer is {}".format(supported_layers, layers)if layers == 50:#ResNet50包含多个模块,其中第2到第5个模块分别包含3、4、6、3个残差块depth = [3, 4, 6, 3]elif layers == 101:#ResNet101包含多个模块,其中第2到第5个模块分别包含3、4、23、3个残差块depth = [3, 4, 23, 3]elif layers == 152:#ResNet152包含多个模块,其中第2到第5个模块分别包含3、8、36、3个残差块depth = [3, 8, 36, 3]# 残差块中使用到的卷积的输出通道数num_filters = [64, 128, 256, 512]# ResNet的第一个模块,包含1个7x7卷积,后面跟着1个最大池化层self.conv = ConvBNLayer(num_channels=3,num_filters=64,filter_size=7,stride=2,act='relu')self.pool2d_max = nn.MaxPool2D(kernel_size=3,stride=2,padding=1)# ResNet的第二到第五个模块c2、c3、c4、c5self.bottleneck_block_list = []num_channels = 64for block in range(len(depth)):     #4(0,1,2,3)shortcut = Falseprint('block=',block,'depth[block]=',depth[block])k=0for i in range(depth[block]):   #depth = [3, 4, 6, 3]k+=1# c3、c4、c5将会在第一个残差块使用stride=2;其余所有残差块stride=1bottleneck_block = self.add_sublayer('bb_%d_%d' % (block, i),BottleneckBlock(num_channels=num_channels,num_filters=num_filters[block],stride=2 if i == 0 and block != 0 else 1, shortcut=shortcut))num_channels = bottleneck_block._num_channels_outself.bottleneck_block_list.append(bottleneck_block)print('bottleneck[',num_channels,num_filters[block],shortcut)shortcut = True;               print('create bnb',k)# 在c5的输出特征图上使用全局池化self.pool2d_avg = paddle.nn.AdaptiveAvgPool2D(output_size=1)# stdv用来作为全连接层随机初始化参数的方差import mathstdv = 1.0 / math.sqrt(2048 * 1.0)# 创建全连接层,输出大小为类别数目,经过残差网络的卷积和全局池化后,# 卷积特征的维度是[B,2048,1,1],故最后一层全连接的输入维度是2048self.out = nn.Linear(in_features=2048, out_features=class_dim,weight_attr=paddle.ParamAttr(initializer=paddle.nn.initializer.Uniform(-stdv, stdv)))def forward(self, inputs):y = self.conv(inputs)y = self.pool2d_max(y)for bottleneck_block in self.bottleneck_block_list:y = bottleneck_block(y)y = self.pool2d_avg(y)y = paddle.reshape(y, [y.shape[0], -1])y = self.out(y)return ydef printStruct(self,inputs):y=paddle.to_tensor(inputs)print(y.shape)y=printItem(self.conv,y)y = self.pool2d_max(y)print("maxpool2d:",y.shape)print('======start bottleneckBlock:')i=0        for bottleneck_block in self.bottleneck_block_list:            print('-----print bottleneckBlock:',i)y = bottleneck_block(y)print('end block:',y.shape)i+=1                       print('======end bottleneckBlock:')y=printItem(self.pool2d_avg,y)y = paddle.reshape(y, [y.shape[0], -1])print('y.shape=',y.shape)        y=printItem(self.out,y)return y# 创建模型
model = ResNet()
# 定义优化器
opt = paddle.optimizer.Momentum(learning_rate=0.001, momentum=0.9, parameters=model.parameters(), weight_decay=0.001)
# 启动训练过程
import PM
#PM.train_pm(model, opt)
## 输入数据形状是 [N, 3, H, W]
# 这里用np.random创建一个随机数组作为输入数据
x = np.random.randn(*[10,3,224,224])
x = x.astype('float32')
# 创建CNN类的实例,指定模型名称和分类的类别数目
#model = VGG(1)
#
model.printStruct(x)
#

训练源代码如下所示:

# -*- coding:utf-8 -*-# ResNet模型代码
import numpy as np
import paddle
import paddle.nn as nn
import paddle.nn.functional as F# ResNet中使用了BatchNorm层,在卷积层的后面加上BatchNorm以提升数值稳定性
# 定义卷积批归一化块  (包括一个卷积)
class ConvBNLayer(paddle.nn.Layer):def __init__(self,num_channels,num_filters,filter_size,stride=1,groups=1,act=None):"""num_channels, 卷积层的输入通道数num_filters, 卷积层的输出通道数stride, 卷积层的步幅groups, 分组卷积的组数,默认groups=1不使用分组卷积"""super(ConvBNLayer, self).__init__()# 创建卷积层self._conv = nn.Conv2D(in_channels=num_channels,out_channels=num_filters,kernel_size=filter_size,stride=stride,padding=(filter_size - 1) // 2,groups=groups,bias_attr=False)# 创建BatchNorm层self._batch_norm = paddle.nn.BatchNorm2D(num_filters)self.act = actdef forward(self, inputs):y = self._conv(inputs)y = self._batch_norm(y)if self.act == 'leaky':y = F.leaky_relu(x=y, negative_slope=0.1)elif self.act == 'relu':y = F.relu(x=y)return y# 定义残差块  (包括三个卷积)
# 每个残差块会对输入图片做三次卷积,然后跟输入图片进行短接
# 如果残差块中第三次卷积输出特征图的形状与输入不一致,则对输入图片做1x1卷积,将其输出形状调整成一致
class BottleneckBlock(paddle.nn.Layer):def __init__(self,num_channels,num_filters,stride,shortcut=True):super(BottleneckBlock, self).__init__()# 创建第一个卷积层 1x1self.conv0 = ConvBNLayer(num_channels=num_channels,num_filters=num_filters,filter_size=1,act='relu')# 创建第二个卷积层 3x3self.conv1 = ConvBNLayer(num_channels=num_filters,num_filters=num_filters,filter_size=3,stride=stride,act='relu')# 创建第三个卷积 1x1,但输出通道数乘以4self.conv2 = ConvBNLayer(num_channels=num_filters,num_filters=num_filters * 4,filter_size=1,act=None)# 如果conv2的输出跟此残差块的输入数据形状一致,则shortcut=True# 否则shortcut = False,添加1个1x1的卷积作用在输入数据上,使其形状变成跟conv2一致if not shortcut:self.short = ConvBNLayer(num_channels=num_channels,num_filters=num_filters * 4,filter_size=1,stride=stride)self.shortcut = shortcutself._num_channels_out = num_filters * 4def forward(self, inputs):y = self.conv0(inputs)conv1 = self.conv1(y)conv2 = self.conv2(conv1)# 如果shortcut=True,直接将inputs跟conv2的输出相加# 否则需要对inputs进行一次卷积,将形状调整成跟conv2输出一致if self.shortcut:short = inputselse:short = self.short(inputs)y = paddle.add(x=short, y=conv2)y = F.relu(y)return y# 定义ResNet模型
class ResNet(paddle.nn.Layer):def __init__(self, layers=50, class_dim=1):"""layers, 网络层数,可以是50, 101或者152class_dim,分类标签的类别数"""super(ResNet, self).__init__()self.layers = layerssupported_layers = [50, 101, 152]assert layers in supported_layers, \"supported layers are {} but input layer is {}".format(supported_layers, layers)if layers == 50:#ResNet50包含多个模块,其中第2到第5个模块分别包含3、4、6、3个残差块depth = [3, 4, 6, 3]elif layers == 101:#ResNet101包含多个模块,其中第2到第5个模块分别包含3、4、23、3个残差块depth = [3, 4, 23, 3]elif layers == 152:#ResNet152包含多个模块,其中第2到第5个模块分别包含3、8、36、3个残差块depth = [3, 8, 36, 3]# 残差块中使用到的卷积的输出通道数num_filters = [64, 128, 256, 512]# ResNet的第一个模块,包含1个7x7卷积,后面跟着1个最大池化层self.conv = ConvBNLayer(num_channels=3,num_filters=64,filter_size=7,stride=2,act='relu')self.pool2d_max = nn.MaxPool2D(kernel_size=3,stride=2,padding=1)# ResNet的第二到第五个模块c2、c3、c4、c5self.bottleneck_block_list = []num_channels = 64for block in range(len(depth)):shortcut = Falsefor i in range(depth[block]):# c3、c4、c5将会在第一个残差块使用stride=2;其余所有残差块stride=1bottleneck_block = self.add_sublayer('bb_%d_%d' % (block, i),BottleneckBlock(num_channels=num_channels,num_filters=num_filters[block],stride=2 if i == 0 and block != 0 else 1, shortcut=shortcut))num_channels = bottleneck_block._num_channels_outself.bottleneck_block_list.append(bottleneck_block)shortcut = True# 在c5的输出特征图上使用全局池化self.pool2d_avg = paddle.nn.AdaptiveAvgPool2D(output_size=1)# stdv用来作为全连接层随机初始化参数的方差import mathstdv = 1.0 / math.sqrt(2048 * 1.0)# 创建全连接层,输出大小为类别数目,经过残差网络的卷积和全局池化后,# 卷积特征的维度是[B,2048,1,1],故最后一层全连接的输入维度是2048self.out = nn.Linear(in_features=2048, out_features=class_dim,weight_attr=paddle.ParamAttr(initializer=paddle.nn.initializer.Uniform(-stdv, stdv)))def forward(self, inputs):y = self.conv(inputs)y = self.pool2d_max(y)for bottleneck_block in self.bottleneck_block_list:y = bottleneck_block(y)y = self.pool2d_avg(y)y = paddle.reshape(y, [y.shape[0], -1])y = self.out(y)return y
# 创建模型
model = ResNet()   #=ResNet(50)   =ResNet(101)   =ResNet(152)
# 定义优化器
opt = paddle.optimizer.Momentum(learning_rate=0.001, momentum=0.9, parameters=model.parameters(), weight_decay=0.001)
# 启动训练过程
import PM
PM.train_pm(model, opt)
#

训练结果:

D:\ProgramData\Anaconda3\lib\site-packages\paddle\nn\layer\norm.py:712: UserWarning: When training, we now always track global mean and variance.warnings.warn(
epoch: 0, batch_id: 0, loss is: 0.7711
epoch: 0, batch_id: 20, loss is: 0.6860
[validation] accuracy/loss: 0.7700/0.4910
epoch: 1, batch_id: 0, loss is: 0.7769
epoch: 1, batch_id: 20, loss is: 0.6261
[validation] accuracy/loss: 0.8475/0.3368
epoch: 2, batch_id: 0, loss is: 0.4543
epoch: 2, batch_id: 20, loss is: 0.3392
[validation] accuracy/loss: 0.8950/0.2690
epoch: 3, batch_id: 0, loss is: 1.1716
epoch: 3, batch_id: 20, loss is: 0.0736
[validation] accuracy/loss: 0.8975/0.2387
epoch: 4, batch_id: 0, loss is: 0.0909
epoch: 4, batch_id: 20, loss is: 0.1900
[validation] accuracy/loss: 0.9375/0.2098
PS E:\project\python> 

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

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

相关文章

【Spring】Spring中的设计模式

文章目录 责任链模式工厂模式适配器模式代理模式模版方法观察者模式构造器模式 责任链模式 Spring中的Aop的通知调用会使用责任链模式责任链模式介绍 角色:抽象处理者(Handler)具体处理者(ConcreteHandler1)客户类角…

Kafka

消息中间件的作用 异步解耦削峰填谷 MQ对比 RabbitMQ 优点:管理界面最好用;支持语言较多; 缺点:不支持扩展(集群) 主要流程:生产者发送消息给交换机,通过路由机制投递到对应的队…

Python入门【​编辑、组合、设计模式_工厂模式实现 、设计模式_单例模式实现、工厂和单例模式结合、异常是什么?异常的解决思路 】(十七)

👏作者简介:大家好,我是爱敲代码的小王,CSDN博客博主,Python小白 📕系列专栏:python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 📧如果文章知识点有错误…

构造方法 与代理

构造方法 public class Son {String name;/*构造方法1.与类名相同2.没有返回值也没有void*//*作用:实例化初始值使用new关键字必须要有构造器*/public Son(){//无参构造方法this.name"sss";}//有参构造方法public Son(String name){//定义有参构造 就必…

【云存储】使用OSS快速搭建个人网盘教程(阿里云)

使用OSS快速搭建个人网盘 一、基础概要1. 主要的存储类型1.1 块存储1.2 文件存储1.3 对象存储 2. 对象存储OSS2.1 存储空间2.2 地域2.3 对象2.4 读写权限2.5 访问域名(Endpoint)2.6 访问密钥2.7 常用功能(1)创建存储空间&#xff…

WebGL Shader着色器GLSL语言

在2D绘图中的坐标系统,默认情况下是与窗口坐标系统相同,它以canvas的左上角为坐标原点,沿X轴向右为正值,沿Y轴向下为正值。其中canvas坐标的单位都是’px’。 WebGL使用的是正交右手坐标系,且每个方向都有可使用的值的…

MFC第二十六天 CRgn类简介与开发、封装CMemoryDC类并应用开发

文章目录 CRgn类简介与开发CRgn类简介CRgn类区域管理开发CRgn类区域管理与不规则形状的选取 封装CMemoryDC类并应用开发CMemoryDC.h封装CMemoryDC开发游戏透明动画CFlashDlg.hCFlashDlg.cpp 封装CMemoryDC开发游戏动画 附录四大窗口CDC派生类 CRgn类简介与开发 CRgn类简介 CR…

c高级:day3

作业: 1. 整理思维导图 2.判断家目录下,普通文件的个数和目录文件的个数 #!/bin/bash ######################################################################## # File Name: zy1.sh # Created Time: 2023年08月04日 星期五 19时13分08秒 ##############################…

计算机网络(2) --- 网络套接字UDP

计算机网络(1) --- 网络介绍_哈里沃克的博客-CSDN博客https://blog.csdn.net/m0_63488627/article/details/131967378?spm1001.2014.3001.5501 目录 1.端口号 2.TCP与UDP协议 1.TCP协议介绍 1.TCP协议 2.UDP协议 3.理解 2.网络字节序 发送逻辑…

html,css日常记录

动态绑定class,当index3!0时,class的值为bdt :class"{bdt:index3!0}" 动态绑定style中的height和lineheight,其中,height的值为函数px(item.length)的返回值,函数名可以随意取。 :style"{height:px(…

SpringBoot使用@Autowired将实现类注入到List或者Map集合中

前言 最近看到RuoYi-Vue-Plus翻译功能 Translation的翻译模块配置类TranslationConfig,其中有一个注入TranslationInterface翻译接口实现类的写法让我感到很新颖,但这种写法在Spring 3.0版本以后就已经支持注入List和Map,平时都没有注意到这…

基于 Redux + TypeScript 实现强类型检查和对 Json 的数据清理

基于 Redux TypeScript 实现强类型检查和对 Json 的数据清理 突然像是打通了任督二脉一样就用了 generics 搞定了之前一直用 any 实现的类型…… 关于 Redux 的部分,这里不多赘述,基本的实现都在这里:Redux Toolkit 调用 API 的四种方式 和…

机器学习概述及其主要算法

目录 1、什么是机器学习 2、数据集 2.1、结构 3、算法分类 4、算法简介 4.1、K-近邻算法 4.2、贝叶斯分类 4.3、决策树和随机森林 4.4、逻辑回归 4.5、神经网络 4.6、线性回归 4.7、岭回归 4.8、K-means 5、机器学习开发流程 6、学习框架 1、什么是机器学习 机器…

Emacs之set-face-attribute与font-lock-add-keywords用法区别(一百二十八)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生…

在java中如何使用openOffice进行格式转换,word,excel,ppt,pdf互相转换

1.首先需要下载并安装openOffice,下载地址为: Apache OpenOffice download | SourceForge.net 2.安装后,可以测试下是否可用; 3.build.gradle中引入依赖: implementation group: com.artofsolving, name: jodconverter, version:…

笔记:Android 9系统启动流程

启动流程 1.按下电源,系统启动 当电源键按下时,引导芯片代码(汇编指令)会从预定的地方(固化在ROM)开始执行,将引导程序 BootLoader 加载到 RAM中,然后执行 2.引导程序 BootLoader …

【3维视觉】3D空间常用算法(点到直线距离、面法线、二面角)

3D空间点到直线的距离 3D空间点到直线的距离 3D空间的曲率 三维空间有三个基本元素,点,线,面。那么曲率是如何定义的呢? 点的曲率? 线的曲率? 面的曲率? 法曲率 设曲面上的曲线在某一点处的切…

Unity 使用SharpZipLib解压时报错

报错信息: NotSupportedException: Encoding 936 data could not be found. Make sure you have correct international System.Text.Encoding.GetEncoding (System.Int32 codepage) ICSharpCode.SharpZipLib.Zip.ZipConstants.ConvertToString。 出现问题分析&…

【SpringBoot】日志是+基于lombok的日志输出

博主简介:想进大厂的打工人博主主页:xyk:所属专栏: JavaEE进阶 在我们日常的程序开发中,日志是程序的重要组成部分,想象⼀下,如果程序报错了,不让你打开控制台看⽇志,那么你能找到报错的原因吗…

leetcode37. 解数独(java)

解数独 解数独题目描述回溯算法代码演示 回溯算法 解数独 难度 困难 leetcode37. 解数独 题目描述 编写一个程序,通过填充空格来解决数独问题。 数独的解法需 遵循如下规则: 1.数字 1-9 在每一行只能出现一次。 2.数字 1-9 在每一列只能出现一次。 3.数字…