Keras搭建分類網(wǎng)絡(luò)平臺VGG16?MobileNet?ResNet50
才發(fā)現(xiàn)做了這么多的博客和視頻,居然從來沒有系統(tǒng)地做過分類網(wǎng)絡(luò),做一個科學(xué)的分類網(wǎng)絡(luò),對身體好。
分類網(wǎng)絡(luò)的常見形式
常見的分類網(wǎng)絡(luò)都可以分為兩部分,一部分是特征提取部分,另一部分是分類部分。
特征提取部分的功能是對輸入進(jìn)來的圖片進(jìn)行特征提取,優(yōu)秀的特征可以幫助更容易區(qū)分目標(biāo),所以特征提取部分一般由各類卷積組成,卷積擁有強(qiáng)大的特征提取能力;
分類部分會利用特征提取部分獲取到的特征進(jìn)行分類,分類部分一般由全連接組成,特征提取部分獲取到的特征一般是一維向量,可以直接進(jìn)行全連接分類。
通常情況下,特征提取部分就是我們平常了解到的各種神經(jīng)網(wǎng)絡(luò),比如VGG、Mobilenet、Resnet等等;而分類部分就是一次或者幾次的全連接,最終我們會獲得一個長度為num_classes的一維向量。
分類網(wǎng)絡(luò)介紹
1、VGG16網(wǎng)絡(luò)介紹
VGG是由Simonyan 和Zisserman在文獻(xiàn)《Very Deep Convolutional Networks for Large Scale Image Recognition》中提出卷積神經(jīng)網(wǎng)絡(luò)模型,其名稱來源于作者所在的牛津大學(xué)視覺幾何組(Visual Geometry Group)的縮寫。
該模型參加2014年的 ImageNet圖像分類與定位挑戰(zhàn)賽,取得了優(yōu)異成績:在分類任務(wù)上排名第二,在定位任務(wù)上排名第一。
它的結(jié)構(gòu)如下圖所示:
這是一個VGG16被用到爛的圖,但確實(shí)很好的反應(yīng)了VGG16的結(jié)構(gòu),整個VGG16由三種不同的層組成,分別是卷積層、最大池化層、全連接層。
VGG16的具體執(zhí)行方式如下:
1、一張?jiān)紙D片被resize到(224,224,3)。
2、conv1:進(jìn)行兩次[3,3]卷積網(wǎng)絡(luò),輸出的特征層為64,輸出為(224,224,64),再進(jìn)行2X2最大池化,輸出net為(112,112,64)。
3、conv2:進(jìn)行兩次[3,3]卷積網(wǎng)絡(luò),輸出的特征層為128,輸出net為(112,112,128),再進(jìn)行2X2最大池化,輸出net為(56,56,128)。
4、conv3:進(jìn)行三次[3,3]卷積網(wǎng)絡(luò),輸出的特征層為256,輸出net為(56,56,256),再進(jìn)行2X2最大池化,輸出net為(28,28,256)。
5、conv4:進(jìn)行三次[3,3]卷積網(wǎng)絡(luò),輸出的特征層為512,輸出net為(28,28,512),再進(jìn)行2X2最大池化,輸出net為(14,14,512)。
6、conv5:進(jìn)行三次[3,3]卷積網(wǎng)絡(luò),輸出的特征層為512,輸出net為(14,14,512),再進(jìn)行2X2最大池化,輸出net為(7,7,512)。
7、對結(jié)果進(jìn)行平鋪。
8、進(jìn)行兩次神經(jīng)元為4096的全連接層。
9、全連接到1000維上,用于進(jìn)行分類。
最后輸出的就是每個類的預(yù)測。
實(shí)現(xiàn)代碼如下:
import warnings from keras.models import Model from keras.layers import Input,Activation,Dropout,Reshape,Conv2D,MaxPooling2D,Dense,Flatten from keras import backend as K def VGG16(input_shape=None, classes=1000): img_input = Input(shape=input_shape) # Block 1 x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input) x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x) # Block 2 x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x) x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x) # Block 3 x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x) x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x) x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x) # Block 4 x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x) x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x) x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x) # Block 5 x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv1')(x) x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2')(x) x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x) x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x) x = Flatten(name='flatten')(x) x = Dense(4096, activation='relu', name='fc1')(x) x = Dense(4096, activation='relu', name='fc2')(x) x = Dense(classes, activation='softmax', name='predictions')(x) inputs = img_input model = Model(inputs, x, name='vgg16') return model
2、MobilenetV1網(wǎng)絡(luò)介紹
MobilenetV1模型是Google針對手機(jī)等嵌入式設(shè)備提出的一種輕量級的深層神經(jīng)網(wǎng)絡(luò),其使用的核心思想便是depthwise separable convolution(深度可分離卷積塊)。
深度可分離卷積塊由兩個部分組成,分別是深度可分離卷積和1x1普通卷積,深度可分離卷積的卷積核大小一般是3x3的,便于理解的話我們可以把它當(dāng)作是特征提取,1x1的普通卷積可以完成通道數(shù)的調(diào)整。
下圖為深度可分離卷積塊的結(jié)構(gòu)示意圖:
深度可分離卷積塊的目的是使用更少的參數(shù)來代替普通的3x3卷積。
我們可以進(jìn)行一下普通卷積和深度可分離卷積塊的對比:
對于普通卷積而言,假設(shè)有一個3×3大小的卷積層,其輸入通道為16、輸出通道為32。具體為,32個3×3大小的卷積核會遍歷16個通道中的每個數(shù)據(jù),最后可得到所需的32個輸出通道,所需參數(shù)為16×32×3×3=4608個。
對于深度可分離卷積結(jié)構(gòu)塊而言,假設(shè)有一個深度可分離卷積結(jié)構(gòu)塊,其輸入通道為16、輸出通道為32,其會用16個3×3大小的卷積核分別遍歷16通道的數(shù)據(jù),得到了16個特征圖譜。在融合操作之前,接著用32個1×1大小的卷積核遍歷這16個特征圖譜,所需參數(shù)為16×3×3+16×32×1×1=656個。
可以看出來深度可分離卷積結(jié)構(gòu)塊可以減少模型的參數(shù)。
深度可分離卷積的代碼如下:
def _depthwise_conv_block(inputs, pointwise_conv_filters, alpha, depth_multiplier=1, strides=(1, 1), block_id=1): pointwise_conv_filters = int(pointwise_conv_filters * alpha) x = DepthwiseConv2D((3, 3), padding='same', depth_multiplier=depth_multiplier, strides=strides, use_bias=False, name='conv_dw_%d' % block_id)(inputs) x = BatchNormalization(name='conv_dw_%d_bn' % block_id)(x) x = Activation(relu6, name='conv_dw_%d_relu' % block_id)(x) x = Conv2D(pointwise_conv_filters, (1, 1), padding='same', use_bias=False, strides=(1, 1), name='conv_pw_%d' % block_id)(x) x = BatchNormalization(name='conv_pw_%d_bn' % block_id)(x) return Activation(relu6, name='conv_pw_%d_relu' % block_id)(x)
通俗地理解深度可分離卷積結(jié)構(gòu)塊,就是3x3的卷積核厚度只有一層,然后在輸入張量上一層一層地滑動,每一次卷積完生成一個輸出通道,當(dāng)卷積完成后,在利用1x1的卷積調(diào)整厚度。
如下就是MobileNet的結(jié)構(gòu),其中Conv dw就是深度可分離卷積,在其之后都會接一個1x1的卷積進(jìn)行通道處理,
在利用特征提取部分完成輸入圖片的特征提取后,我們會利用全局平均池化將特征層調(diào)整成一個特征長條,我們可以將特征長條進(jìn)行全連接,獲得最終的分類結(jié)果。
實(shí)現(xiàn)代碼如下:
import warnings from keras.models import Model from keras.layers import DepthwiseConv2D,Input,Activation,Dropout,Reshape,BatchNormalization,GlobalAveragePooling2D,GlobalMaxPooling2D,Conv2D from keras import backend as K def _conv_block(inputs, filters, alpha, kernel=(3, 3), strides=(1, 1)): filters = int(filters * alpha) x = Conv2D(filters, kernel, padding='same', use_bias=False, strides=strides, name='conv1')(inputs) x = BatchNormalization(name='conv1_bn')(x) return Activation(relu6, name='conv1_relu')(x) def _depthwise_conv_block(inputs, pointwise_conv_filters, alpha, depth_multiplier=1, strides=(1, 1), block_id=1): pointwise_conv_filters = int(pointwise_conv_filters * alpha) x = DepthwiseConv2D((3, 3), padding='same', depth_multiplier=depth_multiplier, strides=strides, use_bias=False, name='conv_dw_%d' % block_id)(inputs) x = BatchNormalization(name='conv_dw_%d_bn' % block_id)(x) x = Activation(relu6, name='conv_dw_%d_relu' % block_id)(x) x = Conv2D(pointwise_conv_filters, (1, 1), padding='same', use_bias=False, strides=(1, 1), name='conv_pw_%d' % block_id)(x) x = BatchNormalization(name='conv_pw_%d_bn' % block_id)(x) return Activation(relu6, name='conv_pw_%d_relu' % block_id)(x) def MobileNet(input_shape=None, alpha=1.0, depth_multiplier=1, dropout=1e-3, classes=1000): img_input = Input(shape=input_shape) # 224,224,3 -> 112,112,32 x = _conv_block(img_input, 32, alpha, strides=(2, 2)) # 112,112,32 -> 112,112,64 x = _depthwise_conv_block(x, 64, alpha, depth_multiplier, block_id=1) # 112,112,64 -> 56,56,128 x = _depthwise_conv_block(x, 128, alpha, depth_multiplier, strides=(2, 2), block_id=2) x = _depthwise_conv_block(x, 128, alpha, depth_multiplier, block_id=3) # 56,56,128 -> 28,28,256 x = _depthwise_conv_block(x, 256, alpha, depth_multiplier, strides=(2, 2), block_id=4) x = _depthwise_conv_block(x, 256, alpha, depth_multiplier, block_id=5) # 28,28,256 -> 14,14,512 x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, strides=(2, 2), block_id=6) x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=7) x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=8) x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=9) x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=10) x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=11) # 14,14,512 -> 7,7,1024 x = _depthwise_conv_block(x, 1024, alpha, depth_multiplier, strides=(2, 2), block_id=12) x = _depthwise_conv_block(x, 1024, alpha, depth_multiplier, block_id=13) # 7,7,1024 -> 1,1,1024 x = GlobalAveragePooling2D()(x) shape = (1, 1, int(1024 * alpha)) x = Reshape(shape, name='reshape_1')(x) x = Dropout(dropout, name='dropout')(x) x = Conv2D(classes, (1, 1),padding='same', name='conv_preds')(x) x = Activation('softmax', name='act_softmax')(x) x = Reshape((classes,), name='reshape_2')(x) inputs = img_input model = Model(inputs, x, name='mobilenet_%0.2f' % (alpha)) return model def relu6(x): return K.relu(x, max_value=6) if __name__ == '__main__': model = MobileNet(input_shape=(224, 224, 3)) model.summary()
3、ResNet50網(wǎng)絡(luò)介紹
a、什么是殘差網(wǎng)絡(luò)
Residual net(殘差網(wǎng)絡(luò)):
將靠前若干層的某一層數(shù)據(jù)輸出直接跳過多層引入到后面數(shù)據(jù)層的輸入部分。
意味著后面的特征層的內(nèi)容會有一部分由其前面的某一層線性貢獻(xiàn)。
其結(jié)構(gòu)如下:
深度殘差網(wǎng)絡(luò)的設(shè)計(jì)是為了克服由于網(wǎng)絡(luò)深度加深而產(chǎn)生的學(xué)習(xí)效率變低與準(zhǔn)確率無法有效提升的問題。
b、什么是ResNet50模型
ResNet50有兩個基本的塊,分別名為Conv Block和Identity Block,其中Conv Block輸入和輸出的維度是不一樣的,所以不能連續(xù)串聯(lián),它的作用是改變網(wǎng)絡(luò)的維度;Identity Block輸入維度和輸出維度相同,可以串聯(lián),用于加深網(wǎng)絡(luò)的。
Conv Block的結(jié)構(gòu)如下,由圖可以看出,Conv Block可以分為兩個部分,左邊部分為主干部分,存在兩次卷積、標(biāo)準(zhǔn)化、激活函數(shù)和一次卷積、標(biāo)準(zhǔn)化;
右邊部分為殘差邊部分,存在一次卷積、標(biāo)準(zhǔn)化,由于殘差邊部分存在卷積,所以我們可以利用Conv Block改變輸出特征層的寬高和通道數(shù):
實(shí)現(xiàn)代碼如下:
def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)): filters1, filters2, filters3 = filters conv_name_base = 'res' + str(stage) + block + '_branch' bn_name_base = 'bn' + str(stage) + block + '_branch' # 降維 x = Conv2D(filters1, (1, 1), strides=strides, name=conv_name_base + '2a')(input_tensor) x = BatchNormalization(name=bn_name_base + '2a')(x) x = Activation('relu')(x) # 3x3卷積 x = Conv2D(filters2, kernel_size, padding='same', name=conv_name_base + '2b')(x) x = BatchNormalization(name=bn_name_base + '2b')(x) x = Activation('relu')(x) # 升維 x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x) x = BatchNormalization(name=bn_name_base + '2c')(x) # 殘差邊 shortcut = Conv2D(filters3, (1, 1), strides=strides, name=conv_name_base + '1')(input_tensor) shortcut = BatchNormalization(name=bn_name_base + '1')(shortcut) x = layers.add([x, shortcut]) x = Activation('relu')(x) return x
Identity Block的結(jié)構(gòu)如下,由圖可以看出,Identity Block可以分為兩個部分,左邊部分為主干部分,存在兩次卷積、標(biāo)準(zhǔn)化、激活函數(shù)和一次卷積、標(biāo)準(zhǔn)化;右邊部分為殘差邊部分,直接與輸出相接,由于殘差邊部分不存在卷積,所以Identity Block的輸入特征層和輸出特征層的shape是相同的,可用于加深網(wǎng)絡(luò):
實(shí)現(xiàn)代碼如下:
def identity_block(input_tensor, kernel_size, filters, stage, block): filters1, filters2, filters3 = filters conv_name_base = 'res' + str(stage) + block + '_branch' bn_name_base = 'bn' + str(stage) + block + '_branch' # 降維 x = Conv2D(filters1, (1, 1), name=conv_name_base + '2a')(input_tensor) x = BatchNormalization(name=bn_name_base + '2a')(x) x = Activation('relu')(x) # 3x3卷積 x = Conv2D(filters2, kernel_size,padding='same', name=conv_name_base + '2b')(x) x = BatchNormalization(name=bn_name_base + '2b')(x) x = Activation('relu')(x) # 升維 x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x) x = BatchNormalization(name=bn_name_base + '2c')(x) x = layers.add([x, input_tensor]) x = Activation('relu')(x) return x
Conv Block和Identity Block都是殘差網(wǎng)絡(luò)結(jié)構(gòu)。
總的網(wǎng)絡(luò)結(jié)構(gòu)如下:
實(shí)現(xiàn)代碼如下:
from __future__ import print_function import numpy as np from keras import layers from keras.layers import Input from keras.layers import Dense,Conv2D,MaxPooling2D,ZeroPadding2D,AveragePooling2D from keras.layers import Activation,BatchNormalization,Flatten from keras.models import Model def identity_block(input_tensor, kernel_size, filters, stage, block): filters1, filters2, filters3 = filters conv_name_base = 'res' + str(stage) + block + '_branch' bn_name_base = 'bn' + str(stage) + block + '_branch' # 降維 x = Conv2D(filters1, (1, 1), name=conv_name_base + '2a')(input_tensor) x = BatchNormalization(name=bn_name_base + '2a')(x) x = Activation('relu')(x) # 3x3卷積 x = Conv2D(filters2, kernel_size,padding='same', name=conv_name_base + '2b')(x) x = BatchNormalization(name=bn_name_base + '2b')(x) x = Activation('relu')(x) # 升維 x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x) x = BatchNormalization(name=bn_name_base + '2c')(x) x = layers.add([x, input_tensor]) x = Activation('relu')(x) return x def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)): filters1, filters2, filters3 = filters conv_name_base = 'res' + str(stage) + block + '_branch' bn_name_base = 'bn' + str(stage) + block + '_branch' # 降維 x = Conv2D(filters1, (1, 1), strides=strides, name=conv_name_base + '2a')(input_tensor) x = BatchNormalization(name=bn_name_base + '2a')(x) x = Activation('relu')(x) # 3x3卷積 x = Conv2D(filters2, kernel_size, padding='same', name=conv_name_base + '2b')(x) x = BatchNormalization(name=bn_name_base + '2b')(x) x = Activation('relu')(x) # 升維 x = Conv2D(filters3, (1, 1), name=conv_name_base + '2c')(x) x = BatchNormalization(name=bn_name_base + '2c')(x) # 殘差邊 shortcut = Conv2D(filters3, (1, 1), strides=strides, name=conv_name_base + '1')(input_tensor) shortcut = BatchNormalization(name=bn_name_base + '1')(shortcut) x = layers.add([x, shortcut]) x = Activation('relu')(x) return x def ResNet50(input_shape=[224,224,3], classes=1000): # 224,224,3 img_input = Input(shape=input_shape) x = ZeroPadding2D((3, 3))(img_input) # [112,112,64] x = Conv2D(64, (7, 7), strides=(2, 2), name='conv1')(x) x = BatchNormalization(name='bn_conv1')(x) x = Activation('relu')(x) x = ZeroPadding2D((1, 1))(x) # [56,56,64] x = MaxPooling2D((3, 3), strides=(2, 2))(x) # [56,56,256] x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1)) x = identity_block(x, 3, [64, 64, 256], stage=2, block='b') x = identity_block(x, 3, [64, 64, 256], stage=2, block='c') # [28,28,512] x = conv_block(x, 3, [128, 128, 512], stage=3, block='a') x = identity_block(x, 3, [128, 128, 512], stage=3, block='b') x = identity_block(x, 3, [128, 128, 512], stage=3, block='c') x = identity_block(x, 3, [128, 128, 512], stage=3, block='d') # [14,14,1024] x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a') x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b') x = identity_block(x, 3, [256, 256, 1024], stage=4, block='c') x = identity_block(x, 3, [256, 256, 1024], stage=4, block='d') x = identity_block(x, 3, [256, 256, 1024], stage=4, block='e') x = identity_block(x, 3, [256, 256, 1024], stage=4, block='f') # [7,7,2048] x = conv_block(x, 3, [512, 512, 2048], stage=5, block='a') x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b') x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c') # 代替全連接層 x = AveragePooling2D((7, 7), name='avg_pool')(x) # 進(jìn)行預(yù)測 x = Flatten()(x) x = Dense(classes, activation='softmax', name='fc1000')(x) model = Model(img_input, x, name='resnet50') return model if __name__ == '__main__': model = ResNet50() model.summary()
分類網(wǎng)絡(luò)的訓(xùn)練
1、LOSS介紹
一般而言,分類網(wǎng)絡(luò)所使用的損失函數(shù)為交叉熵?fù)p失函數(shù),英文名為Cross Entropy,實(shí)現(xiàn)公式如下。
其中:
2、利用分類網(wǎng)絡(luò)進(jìn)行訓(xùn)練
首先前往Github下載對應(yīng)的倉庫,下載完后利用解壓軟件解壓,之后用編程軟件打開文件夾。注意打開的根目錄必須正確,否則相對目錄不正確的情況下,代碼將無法運(yùn)行。一定要注意打開后的根目錄是文件存放的目錄。
a、數(shù)據(jù)集的準(zhǔn)備
datasets文件夾下存放的是訓(xùn)練圖片,分為兩部分,train里面是訓(xùn)練圖片,test里面是測試圖片。
在訓(xùn)練之前需要首先準(zhǔn)備好數(shù)據(jù)集,數(shù)據(jù)集格式為在train和test文件夾下分不同的文件夾,每個文件夾的名稱為對應(yīng)的類別名稱,文件夾下面的圖片為這個類的圖片。
b、數(shù)據(jù)集的處理
在準(zhǔn)備好數(shù)據(jù)集后,需要在根目錄運(yùn)行txt_annotation.py生成訓(xùn)練所需的cls_train.txt。
運(yùn)行前需要修改其中的classes,將其修改成自己需要分的類。
c、開始網(wǎng)絡(luò)訓(xùn)練
通過txt_annotation.py我們已經(jīng)生成了cls_train.txt以及cls_test.txt,此時(shí)我們可以開始訓(xùn)練了。
訓(xùn)練的參數(shù)較多,大家可以在下載庫后仔細(xì)看注釋,其中最重要的部分是修改model_data文件夾下的cls_classes.txt,使其也對應(yīng)自己需要分的類。
在train.py里面調(diào)整自己要選擇的網(wǎng)絡(luò)和權(quán)重后,就可以開始訓(xùn)練了!
以上就是Keras搭建分類網(wǎng)絡(luò)平臺VGG16 MobileNet ResNet50的詳細(xì)內(nèi)容,更多關(guān)于Keras搭建分類網(wǎng)絡(luò)平臺的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
pandas求平均數(shù)和中位數(shù)的方法實(shí)例
pandas對象擁有一組常用的數(shù)學(xué)和統(tǒng)計(jì)方法,大部分都屬于約簡和匯總統(tǒng)計(jì),這篇文章主要給大家介紹了關(guān)于pandas求平均數(shù)和中位數(shù)的相關(guān)資料,需要的朋友可以參考下2021-08-08Python中的枚舉函數(shù)enumerate()的具體用法
本文主要介紹了Python中的枚舉函數(shù)enumerate()的具體用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06Python計(jì)算一個給定時(shí)間點(diǎn)前一個月和后一個月第一天的方法
這篇文章主要介紹了Python計(jì)算一個給定時(shí)間點(diǎn)前一個月和后一個月第一天的方法,涉及Python使用datetime模塊計(jì)算日期時(shí)間的相關(guān)操作技巧,需要的朋友可以參考下2018-05-05使用PyTorch實(shí)現(xiàn)去噪擴(kuò)散模型的完整代碼
在本文中,我們將深入研究DDPM的復(fù)雜性,涵蓋其訓(xùn)練過程,包括正向和逆向過程,并探索如何執(zhí)行采樣,在整個探索過程中,我們將使用PyTorch從頭開始構(gòu)建DDPM,并完成其完整的訓(xùn)練,需要的朋友可以參考下2024-01-01Python獲取android設(shè)備cpu和內(nèi)存占用情況
這篇文章主要介紹了Python獲取android設(shè)備cpu和內(nèi)存占用情況,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-11-11Python實(shí)戰(zhàn)小項(xiàng)目之身份證信息校驗(yàn)
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Python做一個身份證信息校驗(yàn)的小項(xiàng)目,大家可以在過程中查缺補(bǔ)漏,提升水平2021-10-10