tensorflow卷積神經(jīng)Inception?V3網(wǎng)絡(luò)結(jié)構(gòu)代碼解析
前言
學(xué)習(xí)了Inception V3卷積神經(jīng)網(wǎng)絡(luò),總結(jié)一下對(duì)Inception V3網(wǎng)絡(luò)結(jié)構(gòu)和主要代碼的理解。
GoogLeNet對(duì)網(wǎng)絡(luò)中的傳統(tǒng)卷積層進(jìn)行了修改,提出了被稱為 Inception 的結(jié)構(gòu),用于增加網(wǎng)絡(luò)深度和寬度,提高深度神經(jīng)網(wǎng)絡(luò)性能。從Inception V1到Inception V4有4個(gè)更新版本,每一版的網(wǎng)絡(luò)在原來(lái)的基礎(chǔ)上進(jìn)行改進(jìn),提高網(wǎng)絡(luò)性能。本文介紹Inception V3的網(wǎng)絡(luò)結(jié)構(gòu)和主要代碼。
1 非Inception Module的普通卷積層
首先定義一個(gè)非Inception Module的普通卷積層函數(shù)inception_v3_base,輸入?yún)?shù)inputs為圖片數(shù)據(jù)的張量。第1個(gè)卷積層的輸出通道數(shù)為32,卷積核尺寸為【3x3】,步長(zhǎng)為2,padding模式是默認(rèn)的VALID,第1個(gè)卷積層之后的張量尺寸變?yōu)?299-3)/2+1=149,即【149x149x32】。
后面的卷積層采用相同的形式,最后張量尺寸變?yōu)椤?5x35x192】。這幾個(gè)普通的卷積層主要使用了3x3的小卷積核,小卷積核可以低成本的跨通道的對(duì)特征進(jìn)行組合。
def inception_v3_base(inputs,scepe=None): with tf.variable_scope(scope,'InceptionV3',[inputs]): with slim.arg_scope([slim.conv2d,slim.max_pool2d,slim.avg_pool2d],stride=1,padding='VALID'): # 149 x 149 x 32 net = slim.conv2d(inputs,32,[3,3],stride=2,scope='Conv2d_1a_3x3') # 147 x 147 x 32' net = slim.conv2d(net,32),[3,3],scope='Conv2d_2a_3x3') # 147 x 147 x 64 net = slim.conv2d(net,64,[3,3],padding='SAME',scope='Conv2d_2b_3x3') # 73 x 73 x 64 net = slim.max_pool2d(net, [3, 3], stride=2, scope='MaxPool_3a_3x3') # 73 x 73 x 80 net = slim.conv2d(net, 80, [1, 1], scope= 'Conv2d_3b_1x1') # 71 x 71 x 192. net = slim.conv2d(net, 192, [3, 3], scope='Conv2d_4a_3x3',reuse=tf.AUTO_REUSE) # 35 x 35 x 192 net = slim.max_pool2d(net, [3, 3], stride=2, scope= 'MaxPool_5a_3x3')
2 三個(gè)Inception模塊組
接下來(lái)是三個(gè)連續(xù)的Inception模塊組,每個(gè)模塊組有多個(gè)Inception module組成。
下面是第1個(gè)Inception模塊組,包含了3個(gè)類似的Inception module,分別是:Mixed_5b,Mixed_5c,Mixed_5d。第1個(gè)Inception module有4個(gè)分支,
第1個(gè)分支是輸出通道為64的【1x1】卷積,
第2個(gè)分支是輸出通道為48的【1x1】卷積,再連接輸出通道為64的【5x5】卷積,
第3個(gè)分支是輸出通道為64的【1x1】卷積,再連接2個(gè)輸出通道為96的【3x3】卷積,
第4個(gè)分支是【3x3】的平均池化,再連接輸出通道為32的【1x1】卷積。
最后用tf.concat將4個(gè)分支的輸出合并在一起,輸出通道之和為54+64+96+32=256,最后輸出的張量尺寸為【35x35x256】。
第2個(gè)Inception module也有4個(gè)分支,與第1個(gè)模塊類似,只是最后連接輸出通道數(shù)為64的【1x1】卷積,最后輸出的張量尺寸為【35x35x288】。
第3個(gè)模塊與第2個(gè)模塊一樣。
with slim.arg_scope([slim.conv2d,slim.max_pool2d,slim.avg_pool2d],stride=1,padding='SAME'): # 35 x 35 x 256 end_point = 'Mixed_5b' with tf.variable_scope(end_point): with tf.variable_scope('Branch_0'): branch_0 = slim.conv2d(net,depth(64),[1,1],scope='Conv2d_0a_1x1') with tf.variable_scope('Branch_1'): branch_1 = slim.conv2d(net, depth(48), [1, 1], scope='Conv2d_0a_1x1') branch_1 = slim.conv2d(branch_1, depth(64), [5, 5], scope='Conv2d_0b_5x5') with tf.variable_scope('Branch_2'): branch_2 = slim.conv2d(net, depth(64), [1, 1], scope='Conv2d_0a_1x1') branch_2 = slim.conv2d(branch_2, depth(96), [3, 3],scope='Conv2d_0b_3x3') branch_2 = slim.conv2d(branch_2, depth(96), [3, 3], scope='Conv2d_0c_3x3') with tf.variable_scope('Branch_3'): branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3') branch_3 = slim.conv2d(branch_3, depth(32), [1, 1], scope='Conv2d_0b_1x1') net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2, branch_3]) # 64+64+96+32=256 end_points[end_point] = net # 35 x 35 x 288 end_point = 'Mixed_5c' with tf.variable_scope(end_point): with tf.variable_scope('Branch_0'): branch_0 = slim.conv2d(net, depth(64), [1, 1], scope='Conv2d_0a_1x1') with tf.variable_scope('Branch_1'): branch_1 = slim.conv2d(net, depth(48), [1, 1], scope='Conv2d_0b_1x1') branch_1 = slim.conv2d(branch_1, depth(64), [5, 5],scope='Conv_1_0c_5x5') with tf.variable_scope('Branch_2'): branch_2 = slim.conv2d(net, depth(64), [1, 1],scope='Conv2d_0a_1x1') branch_2 = slim.conv2d(branch_2, depth(96), [3, 3],scope='Conv2d_0b_3x3') branch_2 = slim.conv2d(branch_2, depth(96), [3, 3],scope='Conv2d_0c_3x3') with tf.variable_scope('Branch_3'): branch_3 = slim.avg_pool2d(net, [3, 3],scope='AvgPool_0a_3x3') branch_3 = slim.conv2d(branch_3, depth(64), [1, 1],scope='Conv2d_0b_1x1') net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2, branch_3]) end_points[end_point] = net # 35 x 35 x 288 end_point = 'Mixed_5d' with tf.variable_scope(end_point): with tf.variable_scope('Branch_0'): branch_0 = slim.conv2d(net, depth(64), [1, 1], scope='Conv2d_0a_1x1') with tf.variable_scope('Branch_1'): branch_1 = slim.conv2d(net, depth(48), [1, 1], scope='Conv2d_0a_1x1') branch_1 = slim.conv2d(branch_1, depth(64), [5, 5],scope='Conv2d_0b_5x5') with tf.variable_scope('Branch_2'): branch_2 = slim.conv2d(net, depth(64), [1, 1], scope='Conv2d_0a_1x1') branch_2 = slim.conv2d(branch_2, depth(96), [3, 3],scope='Conv2d_0b_3x3') branch_2 = slim.conv2d(branch_2, depth(96), [3, 3],scope='Conv2d_0c_3x3') with tf.variable_scope('Branch_3'): branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3') branch_3 = slim.conv2d(branch_3, depth(64), [1, 1],scope='Conv2d_0b_1x1') net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2, branch_3]) end_points[end_point] = net
第2個(gè)Inception模塊組包含了5個(gè)Inception module,分別是Mixed_6a,Mixed_6b,Mixed_6ac,Mixed_6d,Mixed_6e。
每個(gè)Inception module包含有多個(gè)分支,第1個(gè)Inception module的步長(zhǎng)為2,因此圖片尺寸被壓縮,最后輸出的張量尺寸為【17x17x768】。
第2個(gè)Inception module采用了Fractorization into small convolutions思想,串聯(lián)了【1x7】和【7x1】卷積,最后也是將多個(gè)通道合并。
第3、4個(gè)Inception module與第2個(gè)類似,都是用來(lái)增加卷積和非線性變化,提煉特征。張量尺寸不變,多個(gè)module后仍舊是【17x17x768】。
# 17 x 17 x 768. end_point = 'Mixed_6a' with tf.variable_scope(end_point): with tf.variable_scope('Branch_0'): branch_0 = slim.conv2d(net, depth(384), [3, 3], stride=2,padding='VALID', scope='Conv2d_1a_1x1') with tf.variable_scope('Branch_1'): branch_1 = slim.conv2d(net, depth(64), [1, 1], scope='Conv2d_0a_1x1') branch_1 = slim.conv2d(branch_1, depth(96), [3, 3],scope='Conv2d_0b_3x3') branch_1 = slim.conv2d(branch_1, depth(96), [3, 3], stride=2,padding='VALID', scope='Conv2d_1a_1x1') with tf.variable_scope('Branch_2'): branch_2 = slim.max_pool2d(net, [3, 3], stride=2, padding='VALID',scope='MaxPool_1a_3x3') net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2]) # (35-3)/2+1=17 end_points[end_point] = net # 17 x 17 x 768. end_point = 'Mixed_6b' with tf.variable_scope(end_point): with tf.variable_scope('Branch_0'): branch_0 = slim.conv2d(net, depth(192), [1, 1], scope='Conv2d_0a_1x1') with tf.variable_scope('Branch_1'): branch_1 = slim.conv2d(net, depth(128), [1, 1], scope='Conv2d_0a_1x1') branch_1 = slim.conv2d(branch_1, depth(128), [1, 7],scope='Conv2d_0b_1x7') branch_1 = slim.conv2d(branch_1, depth(192), [7, 1],scope='Conv2d_0c_7x1') with tf.variable_scope('Branch_2'): branch_2 = slim.conv2d(net, depth(128), [1, 1], scope='Conv2d_0a_1x1') branch_2 = slim.conv2d(branch_2, depth(128), [7, 1],scope='Conv2d_0b_7x1') branch_2 = slim.conv2d(branch_2, depth(128), [1, 7],scope='Conv2d_0c_1x7') branch_2 = slim.conv2d(branch_2, depth(128), [7, 1], scope='Conv2d_0d_7x1') branch_2 = slim.conv2d(branch_2, depth(192), [1, 7],scope='Conv2d_0e_1x7') with tf.variable_scope('Branch_3'): branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3') branch_3 = slim.conv2d(branch_3, depth(192), [1, 1],scope='Conv2d_0b_1x1') net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2, branch_3]) end_points[end_point] = net print(net.shape) # 17 x 17 x 768. end_point = 'Mixed_6c' with tf.variable_scope(end_point): with tf.variable_scope('Branch_0'): ranch_0 = slim.conv2d(net, depth(192), [1, 1], scope='Conv2d_0a_1x1') with tf.variable_scope('Branch_1'): branch_1 = slim.conv2d(net, depth(160), [1, 1], scope='Conv2d_0a_1x1') branch_1 = slim.conv2d(branch_1, depth(160), [1, 7],scope='Conv2d_0b_1x7') branch_1 = slim.conv2d(branch_1, depth(192), [7, 1],scope='Conv2d_0c_7x1') with tf.variable_scope('Branch_2'): branch_2 = slim.conv2d(net, depth(160), [1, 1], scope='Conv2d_0a_1x1') branch_2 = slim.conv2d(branch_2, depth(160), [7, 1],scope='Conv2d_0b_7x1') branch_2 = slim.conv2d(branch_2, depth(160), [1, 7],scope='Conv2d_0c_1x7') branch_2 = slim.conv2d(branch_2, depth(160), [7, 1],scope='Conv2d_0d_7x1') branch_2 = slim.conv2d(branch_2, depth(192), [1, 7],scope='Conv2d_0e_1x7') with tf.variable_scope('Branch_3'): branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3') branch_3 = slim.conv2d(branch_3, depth(192), [1, 1],scope='Conv2d_0b_1x1') net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2, branch_3]) end_points[end_point] = net # 17 x 17 x 768. end_point = 'Mixed_6d' with tf.variable_scope(end_point): with tf.variable_scope('Branch_0'): branch_0 = slim.conv2d(net, depth(192), [1, 1], scope='Conv2d_0a_1x1') with tf.variable_scope('Branch_1'): branch_1 = slim.conv2d(net, depth(160), [1, 1], scope='Conv2d_0a_1x1') branch_1 = slim.conv2d(branch_1, depth(160), [1, 7], scope='Conv2d_0b_1x7') branch_1 = slim.conv2d(branch_1, depth(192), [7, 1], scope='Conv2d_0c_7x1') with tf.variable_scope('Branch_2'): branch_2 = slim.conv2d(net, depth(160), [1, 1], scope='Conv2d_0a_1x1') branch_2 = slim.conv2d(branch_2, depth(160), [7, 1], scope='Conv2d_0b_7x1') branch_2 = slim.conv2d(branch_2, depth(160), [1, 7], scope='Conv2d_0c_1x7') branch_2 = slim.conv2d(branch_2, depth(160), [7, 1], scope='Conv2d_0d_7x1') branch_2 = slim.conv2d(branch_2, depth(192), [1, 7], scope='Conv2d_0e_1x7') with tf.variable_scope('Branch_3'): branch_3 = slim.avg_pool2d(net, [3, 3], sco e='AvgPool_0a_3x3') branch_3 = slim.conv2d(branch_3, depth(192), [1, 1],scope='Conv2d_0b_1x1') net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2, branch_3]) end_points[end_point] = net # 17 x 17 x 768. end_point = 'Mixed_6e' with tf.variable_scope(end_point): with tf.variable_scope('Branch_0'): branch_0 = slim.conv2d(net, depth(192), [1, 1], scope='Conv2d_0a_1x1') with tf.variable_scope('Branch_1'): branch_1 = slim.conv2d(net, depth(192), [1, 1], scope='Conv2d_0a_1x1') branch_1 = slim.conv2d(branch_1, depth(192), [1, 7], scope='Conv2d_0b_1x7') branch_1 = slim.conv2d(branch_1, depth(192), [7, 1], scope='Conv2d_0c_7x1') with tf.variable_scope('Branch_2'): branch_2 = slim.conv2d(net, depth(192), [1, 1], scope='Conv2d_0a_1x1') branch_2 = slim.conv2d(branch_2, depth(192), [7, 1], scope='Conv2d_0b_7x1') branch_2 = slim.conv2d(branch_2, depth(192), [1, 7], scope='Conv2d_0c_1x7') branch_2 = slim.conv2d(branch_2, depth(192), [7, 1], scope='Conv2d_0d_7x1') branch_2 = slim.conv2d(branch_2, depth(192), [1, 7], scope='Conv2d_0e_1x7') with tf.variable_scope('Branch_3'): branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3') branch_3 = slim.conv2d(branch_3, depth(192), [1, 1], scope='Conv2d_0b_1x1') net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2, branch_3]) end_points[end_point] = net
第3個(gè)Inception模塊組包含了3個(gè)Inception module,分別是Mxied_7a,Mixed_7b,Mixed_7c。
第1個(gè)Inception module包含了3個(gè)分支,與上面的結(jié)構(gòu)類似,主要也是通過(guò)改變通道數(shù)、卷積核尺寸,包括【1x1】、【3x3】、【1x7】、【7x1】來(lái)增加卷積和非線性變化,提升網(wǎng)絡(luò)性能。
最后3個(gè)分支在輸出通道上合并,輸出張量的尺寸為【8 x 8 x 1280】。第3個(gè)Inception module后得到的張量尺寸為【8 x 8 x 2048】。
# 8 x 8 x 1280. end_point = 'Mixed_7a' with tf.variable_scope(end_point): with tf.variable_scope('Branch_0'): branch_0 = slim.conv2d(net, depth(192), [1, 1], scope='Conv2d_0a_1x1') branch_0 = slim.conv2d(branch_0, depth(320), [3, 3], stride=2, padding='VALID', scope='Conv2d_1a_3x3') with tf.variable_scope('Branch_1'): branch_1 = slim.conv2d(net, depth(192), [1, 1], scope='Conv2d_0a_1x1') branch_1 = slim.conv2d(branch_1, depth(192), [1, 7], scope='Conv2d_0b_1x7') branch_1 = slim.conv2d(branch_1, depth(192), [7, 1], scope='Conv2d_0c_7x1') branch_1 = slim.conv2d(branch_1, depth(192), [3, 3], stride=2, padding='VALID', scope='Conv2d_1a_3x3') with tf.variable_scope('Branch_2'): branch_2 = slim.max_pool2d(net, [3, 3], stride=2, padding='VALID', scope='MaxPool_1a_3x3') net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2]) end_points[end_point] = net # 8 x 8 x 2048. end_point = 'Mixed_7b' with tf.variable_scope(end_point): with tf.variable_scope('Branch_0'): branch_0 = slim.conv2d(net, depth(320), [1, 1], scope='Conv2d_0a_1x1') with tf.variable_scope('Branch_1'): branch_1 = slim.conv2d(net, depth(384), [1, 1], scope='Conv2d_0a_1x1') branch_1 = tf.concat(axis=3, values=[ slim.conv2d(branch_1, depth(384), [1, 3], scope='Conv2d_0b_1x3'), slim.conv2d(branch_1, depth(384), [3, 1], scope='Conv2d_0b_3x1')]) with tf.variable_scope('Branch_2'): branch_2 = slim.conv2d(net, depth(448), [1, 1], scope='Conv2d_0a_1x1') branch_2 = slim.conv2d( branch_2, depth(384), [3, 3], scope='Conv2d_0b_3x3') branch_2 = tf.concat(axis=3, values=[ slim.conv2d(branch_2, depth(384), [1, 3], scope='Conv2d_0c_1x3'), slim.conv2d(branch_2, depth(384), [3, 1], scope='Conv2d_0d_3x1')]) with tf.variable_scope('Branch_3'): branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3') branch_3 = slim.conv2d( branch_3, depth(192), [1, 1], scope='Conv2d_0b_1x1') net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2, branch_3]) end_points[end_point] = net) # 8 x 8 x 2048. end_point = 'Mixed_7c' with tf.variable_scope(end_point): with tf.variable_scope('Branch_0'): branch_0 = slim.conv2d(net, depth(320), [1, 1], scope='Conv2d_0a_1x1') with tf.variable_scope('Branch_1'): branch_1 = slim.conv2d(net, depth(384), [1, 1], scope='Conv2d_0a_1x1') branch_1 = tf.concat(axis=3, values=[ slim.conv2d(branch_1, depth(384), [1, 3], scope='Conv2d_0b_1x3'), slim.conv2d(branch_1, depth(384), [3, 1], scope='Conv2d_0c_3x1')]) with tf.variable_scope('Branch_2'): branch_2 = slim.conv2d(net, depth(448), [1, 1], scope='Conv2d_0a_1x1') branch_2 = slim.conv2d( branch_2, depth(384), [3, 3], scope='Conv2d_0b_3x3') branch_2 = tf.concat(axis=3, values=[ slim.conv2d(branch_2, depth(384), [1, 3], scope='Conv2d_0c_1x3'), slim.conv2d(branch_2, depth(384), [3, 1], scope='Conv2d_0d_3x1')]) with tf.variable_scope('Branch_3'): branch_3 = slim.avg_pool2d(net, [3, 3], scope='AvgPool_0a_3x3') branch_3 = slim.conv2d( branch_3, depth(192), [1, 1], scope='Conv2d_0b_1x1') net = tf.concat(axis=3, values=[branch_0, branch_1, branch_2, branch_3]) end_points[end_point] = net
3 Auxiliary Logits、全局平均池化、Softmax分類
Inception V3網(wǎng)絡(luò)的最后一部分是Auxiliary Logits、全局平均池化、Softmax分類。
首先是Auxiliary Logits,作為輔助分類的節(jié)點(diǎn),對(duì)分類結(jié)果預(yù)測(cè)有很大幫助。
先通過(guò)end_points['Mixed_6e']得到Mixed_6e后的特征張量,之后接一個(gè)【5x5】的平均池化,步長(zhǎng)為3,padding為VALID,張量尺寸從第2個(gè)模塊組的【17x17x768】變?yōu)椤?x5x768】。
接著連接一個(gè)輸出通道為128的【1x1】卷積和輸出通道為768的【5x5】卷積,輸出尺寸變?yōu)椤?x1x768】。
然后連接輸出通道數(shù)為num_classes的【1x1】卷積,輸出變?yōu)椤?x1x1000】。最后將輔助分類節(jié)點(diǎn)的輸出存儲(chǔ)到字典表end_points中。
with slim.arg_scope([slim.conv2d,slim.max_pool2d,slim.avg_pool2d],stride=1,padding='SAME'): aux_logits = end_points['Mixed_6e'] print(aux_logits.shape) with tf.variable_scope('AuxLogits'): aux_logits = slim.avg_pool2d(aux_logits,[5,5],stride=3,padding='VALID',scope='AvgPool_1a_5x5') aux_logits = slim.conv2d(aux_logits,depth(128),[1,1],scope='Conv2d_1b_1x1') # (17-5)/3+1=5 kernel_size = _reduced_kernel_size_for_small_input(aux_logits, [5, 5]) aux_logits = slim.conv2d(aux_logits, depth(768), kernel_size, weights_initializer=trunc_normal(0.01), padding='VALID', scope='Conv2d_2a_{}x{}'.format(*kernel_size)) aux_logits = slim.conv2d( aux_logits, num_classes, [1, 1], activation_fn=None, normalizer_fn=None, weights_initializer=trunc_normal(0.001), scope='Conv2d_2b_1x1') aux_logits = tf.squeeze(aux_logits, [1, 2], name='SpatialSqueeze') end_points['AuxLogits'] = aux_logits
最后對(duì)最后一個(gè)卷積層的輸出Mixed_7c進(jìn)行一個(gè)【8x8】的全局平均池化,padding為VALID,輸出張量從【8 x 8 x 2048】變?yōu)椤? x 1 x 2048】,然后連接一個(gè)Dropout層,接著連接一個(gè)輸出通道數(shù)為1000的【1x1】卷積。
使用tf.squeeze去掉輸出張量中維數(shù)為1的維度。最后用Softmax得到最終分類結(jié)果。返回分類結(jié)果logits和包含各個(gè)卷積后的特征圖字典表end_points。
with tf.variable_scope('Logits'): kernel_size = _reduced_kernel_size_for_small_input(net, [8, 8]) net = slim.avg_pool2d(net, kernel_size, padding='VALID',scope='AvgPool_1a_{}x{}'.format(*kernel_size)) end_points['AvgPool_1a'] = net net = slim.dropout(net, keep_prob=dropout_keep_prob, scope='Dropout_1b') end_points['PreLogits'] = net logits = slim.conv2d(net, num_classes, [1, 1], activation_fn=None, normalizer_fn=None, scope='Conv2d_1c_1x1') logits = tf.squeeze(logits, [1, 2], name='SpatialSqueeze') end_points['Logits'] = logits end_points['Predictions'] = slim.softmax(logits, scope='Predictions') return logits,end_points
參考文獻(xiàn):
1. 《TensorFlow實(shí)戰(zhàn)》
以上就是卷積神經(jīng)Inception V3網(wǎng)絡(luò)結(jié)構(gòu)代碼解析的詳細(xì)內(nèi)容,更多關(guān)于Inception V3卷積神經(jīng)網(wǎng)絡(luò)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
python+pyqt實(shí)現(xiàn)12306圖片驗(yàn)證效果
這篇文章主要為大家詳細(xì)介紹了python+pyqt實(shí)現(xiàn)12306圖片驗(yàn)證效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Python實(shí)現(xiàn)智慧校園自動(dòng)評(píng)教全新版
上一次的智慧校園自動(dòng)評(píng)教是用的selenium庫(kù)去模擬人去對(duì)瀏覽器進(jìn)行點(diǎn)擊操作,雖然比手動(dòng)評(píng)教要快,但是效率還是不高.從而想去嘗試重新寫一份不用selenium的評(píng)教方案,功夫不負(fù)有心人,最終成功了,需要的朋友可以參考下2021-06-06使用Python-OpenCV消除圖像中孤立的小區(qū)域操作
這篇文章主要介紹了使用Python-OpenCV消除圖像中孤立的小區(qū)域操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07詳解用pyecharts Geo實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)熱力圖城市找不到問(wèn)題解決
這篇文章主要介紹了詳解用pyecharts Geo實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)熱力圖城市找不到問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06Python編程實(shí)現(xiàn)雙擊更新所有已安裝python模塊的方法
這篇文章主要介紹了Python編程實(shí)現(xiàn)雙擊更新所有已安裝python模塊的方法,涉及Python針對(duì)模塊操作命令的相關(guān)封裝與調(diào)用技巧,需要的朋友可以參考下2017-06-06python數(shù)據(jù)抓取分析的示例代碼(python + mongodb)
本篇文章主要介紹了python數(shù)據(jù)抓取分析的示例代碼(python + mongodb),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12關(guān)于matplotlib及相關(guān)cmap參數(shù)的取值方式
這篇文章主要介紹了關(guān)于matplotlib及相關(guān)cmap參數(shù)的取值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11