La position actuelle:Accueil du site>[Note de thèse] lsnet: Extremely Light Weight siame Network for Change Detection in Remote Sensing Image
[Note de thèse] lsnet: Extremely Light Weight siame Network for Change Detection in Remote Sensing Image
2022-05-15 07:20:32【M0 61899108】
Documents
Titre de la thèse:LSNET: EXTREMELY LIGHT-WEIGHT SIAMESE NETWORK FOR CHANGE DETECTIONOF REMOTE SENSING IMAGE
Livraison:CVPR 2022
Adresse de la thèse:https://arxiv.org/abs/2201.09156
Adresse du projet:https://github.com/qaz670756/LSNet
L'idée de la thèse est simple , Deux modifications majeures ont été apportées. , Premièrement, la légèreté du réseau de base ,AdoptionCGB Le module construit un double réseau de base léger ; D'autre part, l'amélioration de la fusion pyramidale des caractéristiques ,IndenseFPNBasé sur l'amélioration, Supprimer les connexions redondantes , Augmenter le chemin de fusion du bas vers le haut . La raison pour laquelle les paramètres du modèle et le calcul sont considérablement réduits est la légèreté du réseau de base. , La Convolution séparable en profondeur est utilisée au lieu de la convolution ordinaire .
Résultats expérimentaux
Paramètres officiels de formation :
{
"patch_size": 256,
"augmentation": true,
"num_gpus": 1,
"num_workers": 8,
"num_channel": 3,
"EF": false,
"epochs": 101,
"batch_size": 12,
"learning_rate": 1e-3,
"model_name": "denseFPN",
"loss_function": "contra_hybrid",
"dataset_dir": "data/Real/subset/",
"weight_dir": "./outputs/",
"log_dir": "./log/"
}
Abstract
Les réseaux jumeaux deviennent progressivement des images de télédétection (remote sensing image,RSI) Mainstream of Change Detection . Mais avec la structure 、 La complexité des modules et des processus de formation , Les modèles sont plus complexes , Difficile à appliquer dans la pratique .
Cet article, Proposer une méthode pour RSI Réseau jumeau ultra - léger pour la détection des changements (Light-Weight Siamese Network,LSNet), Remplacement de la convolution standard par la convolution des cavités de convolution séparables en profondeur , Et supprimer les connexions denses redondantes , Seuls les flux de caractéristiques valides sont conservés lors de la fusion de caractéristiques jumelles , Les paramètres et les calculs sont considérablement réduits .InCDDSur l'ensemble de données, Comparé au premier modèle ,LSNet Les paramètres et les calculs ont été réduits respectivement de 90.35%Et91.34%, La précision n'a diminué que 1.5%.
Introduction
TraditionnelRSI La méthode de détection des changements dépend des caractéristiques artificielles et du temps nécessaire avant et après le traitement. , Difficulté à distinguer les changements sémantiques des bruits de fond .
Les paires d'images peuvent être entrées directement dans le réseau de convolution jumelle ,Aucun prétraitement n'est nécessaire, L'apprentissage supervisé de bout en bout peut séparer la région de changement sémantique de la région invariante .
- Dans cet article, nous présentons un réseau jumeau Léger LSNet,Très efficace,Comme le montre la figure1. L'épine dorsale du réseau utilise un module de démarrage contextuel (Context Guide Block,CGB)Construire, Le module est basé sur la convolution des cavités séparables en profondeur et l'agrégation globale des caractéristiques. .Utilisation comparativeResNet-50 En tant que tronc ,LSNet La quantité de paramètres et la quantité de calcul de la colonne vertébrale sont les mêmes que celles de la colonne vertébrale originale. 3.97%Et32.56%.
- Proposer un réseau pyramidal de caractéristiques différentielles (diffFPN) Pour l'extraction progressive des caractéristiques et la récupération de la résolution ( Éliminer les connexions redondantes tout en maintenant le flux caractéristique ), Enfin, la région d'image modifiée est séparée de la région d'image constante .
Method
LSNet: Y compris une double dorsale (LightSiamese Backbone) Et un réseau pyramidal de caractéristiques différentielles (diffFPN). L'épine dorsale utilise un module de démarrage contextuel (CGB)Construire,diffFPN Pour une fusion efficace de paires de caractéristiques jumelles .
Light-Siamese backbone
ImagesT1EtT2 Tronc de réseau jumeau avec poids partagé , L'épine dorsale est constituée de 4 Composé de couches composites (De haut en bas, Les couches composites sont composées respectivement de 3/3/8/12- Oui.CGBComposition du module),ChaqueCGB équivalent à deux niveaux ,Il y a donc4 Sortie des caractéristiques du Groupe ,Total52Couche.
Éléments de base(Context Guide Block)CGBComme le montre la figure2Sur la droite.EntréeX Après une expansion parallèle (Gonflement)Convolution, Pour obtenir une gamme différente (Sentir la nature sauvage) Informations contextuelles locales pour . La Convolution d'expansion est calculée de façon séparable en profondeur , C'est - à - dire que tous les canaux sont groupés , La Convolution ne fonctionne que dans un seul groupe .(Convolution séparable en profondeur, Peut réduire considérablement la quantité de calcul , Mais il y a une limite de vitesse , Le goulot d'étranglement est la largeur de bande d'accès )
Interaction des canaux et extraction globale de l'information .
Differential feature pyramid network
SUNNet Une méthode de fusion pyramidale des caractéristiques avec des connexions denses est proposée ,Fig.3(a)Comme indiqué,
Ce genre dedenseFPNPrésence structurelle2Questions:
- Connexions redondantes.(T_1,0、T_2,0 Les caractéristiques isosuperficielles sont entrées à plusieurs reprises dans d_1,0、d_2,0、d_3,0Moyenne,Inefficacité)
- Flux de caractéristiques irrationnels .(denseFPNMoyenne,Couche de sortied_0,0Etd_1,0 Contient des caractéristiques incomplètes du tronc )
Et donc,,Présentation du documentdiffFPPNStructure, Supprimer les connexions redondantes , Ajout d'un chemin de fusion de bas en haut , Faire en sorte que les trois couches de sortie contiennent des caractéristiques complètes du réseau de base .
Experiment and Results
Dataset and evaluation metrics
Ensemble de données:CDD
Indicateurs communs: precision、recall、F1-score、overall accuracy
Indicateurs quantitatifs:F1-G、F1-F ( Quantifier les paramètres unitaires et calculer les paires de quantités séparément F1 Effets des scores ),F1-Eff( Évaluer l'efficacité globale du modèle )
Accuracy and efficiency comparison
Comparaison des paramètres et des calculs entre deux modules (CDDEnsemble de données), Comme le montre le tableau ,
- Comparé àResNet-50,LightSiamese-52 La quantité de paramètres et la quantité de calcul de la colonne vertébrale sont les mêmes que celles de la colonne vertébrale originale. 1/25Et1/3.
- denseFPN Il y a un flux caractéristique irrationnel dans la structure de ,diffFPN Pour ne soulever que 0.0709M Lorsque la quantité de paramètre est ,Réduction du calcul1.0884GFLOPs, Réduction de plus de la moitié .
Plusieurs façons de CDD Comparaison des performances dans l'ensemble de données ,LSNet Tous les indices de performance de la méthode sont également ok, Top 3 .
Comparaison de l'efficacité de plusieurs méthodes ,Utilisation visiblediffFPN La méthode de F1-PEtF1-G.
Tableau combiné2Et des graphiques3,AvecSNUNetComparé à,LSNet Les paramètres et les calculs ont été réduits respectivement de 90.35%Et91.34%,Précision réduite seulement1.5%.
LSNetRésultats visuels pour. Les résultats sont relativement précis , Mais les détails des bords doivent être affinés .(e)Comme vous pouvez le voir, Le bord de la zone de changement est plus élevé que la probabilité interne , Il montre que le réseau utilise la structure de la région comme caractéristique d'identification , Améliore sa robustesse aux changements de couleur et de texture .
Conclusion
Pour détecter efficacement RSIChangement, Un réseau de jumelage léger est proposé , Le réseau a un module de démarrage contextuel (CGB) Le tronc jumeau léger construit (LightSiamese Backbone) Module de fusion de paires de caractéristiques (diffFPN).Dans lesCCDLes résultats sur l'ensemble de données montrent que, Par rapport à d'autres approches dominantes , La méthode obtient des résultats compétitifs avec des paramètres et des calculs limités , Son efficacité a été démontrée .
Code de base
Context Guide Block
class ContextGuidedBlock(nn.Module):
"""Context Guided Block for CGNet.
This class consists of four components: local feature extractor,
surrounding feature extractor, joint feature extractor and global
context extractor.
Args:
in_channels (int): Number of input feature channels.
out_channels (int): Number of output feature channels.
dilation (int): Dilation rate for surrounding context extractor.
Default: 2.
reduction (int): Reduction for global context extractor. Default: 16.
skip_connect (bool): Add input to output or not. Default: True.
downsample (bool): Downsample the input to 1/2 or not. Default: False.
conv_cfg (dict): Config dict for convolution layer.
Default: None, which means using conv2d.
norm_cfg (dict): Config dict for normalization layer.
Default: dict(type='BN', requires_grad=True).
act_cfg (dict): Config dict for activation layer.
Default: dict(type='PReLU').
with_cp (bool): Use checkpoint or not. Using checkpoint will save some
memory while slowing down the training speed. Default: False.
"""
def __init__(self,
in_channels,
out_channels,
dilation=2,
reduction=16,
skip_connect=True,
downsample=False,
conv_cfg=None,
norm_cfg=dict(type='BN', requires_grad=True),
act_cfg=dict(type='PReLU'),
with_cp=False):
super(ContextGuidedBlock, self).__init__()
self.with_cp = with_cp
self.downsample = downsample
# channels = out_channels if downsample else out_channels // 2
channels = out_channels // 2
if 'type' in act_cfg and act_cfg['type'] == 'PReLU':
act_cfg['num_parameters'] = channels
kernel_size = 3 if downsample else 1
stride = 2 if downsample else 1
padding = (kernel_size - 1) // 2
# self.channel_shuffle = ChannelShuffle(2 if in_channels==in_channels//2*2 else in_channels)
self.conv1x1 = nn.Sequential(
nn.Conv2d(in_channels, channels, kernel_size=kernel_size, stride=stride, padding=padding),
build_norm_layer(channels),
nn.PReLU(num_parameters=channels)
)
self.f_loc = nn.Conv2d(channels, channels, kernel_size=3,
padding=1, groups=channels, bias=False)
self.f_sur = nn.Conv2d(channels, channels, kernel_size=3, padding=dilation,
dilation=dilation, groups=channels, bias=False)
self.bn = build_norm_layer(2 * channels)
self.activate = nn.PReLU(2 * channels)
# original bottleneck in CGNet: A light weight context guided network for segmantic segmentation
# is removed for saving computation amount
# if downsample:
# self.bottleneck = build_conv_layer(
# conv_cfg,
# 2 * channels,
# out_channels,
# kernel_size=1,
# bias=False)
self.skip_connect = skip_connect and not downsample
self.f_glo = GlobalContextExtractor(out_channels, reduction, with_cp)
# self.f_glo = CoordAtt(out_channels,out_channels,groups=reduction)
def forward(self, x):
def _inner_forward(x):
# x = self.channel_shuffle(x)
out = self.conv1x1(x)
loc = self.f_loc(out)
sur = self.f_sur(out)
joi_feat = torch.cat([loc, sur], 1) # the joint feature
joi_feat = self.bn(joi_feat)
joi_feat = self.activate(joi_feat)
if self.downsample:
pass
# joi_feat = self.bottleneck(joi_feat) # channel = out_channels
# f_glo is employed to refine the joint feature
out = self.f_glo(joi_feat)
if self.skip_connect:
return x + out
else:
return out
return _inner_forward(x)
def cgblock(in_ch, out_ch, dilation=2, reduction=8, skip_connect=False):
return nn.Sequential(
ContextGuidedBlock(in_ch, out_ch,
dilation=dilation,
reduction=reduction,
downsample=False,
skip_connect=skip_connect))
light_siamese_backbone
class light_siamese_backbone(nn.Module):
def __init__(self, in_ch=None, num_blocks=None, cur_channels=None,
filters=None, dilations=None, reductions=None):
super(light_siamese_backbone, self).__init__()
norm_cfg = {'type': 'BN', 'eps': 0.001, 'requires_grad': True}
act_cfg = {'type': 'PReLU', 'num_parameters': 32}
self.inject_2x = InputInjection(1) # down-sample for Input, factor=2
self.inject_4x = InputInjection(2) # down-sample for Input, factor=4
# stage 0
self.stem = nn.ModuleList()
for i in range(num_blocks[0]):
self.stem.append(
ContextGuidedBlock(
cur_channels[0], filters[0],
dilations[0], reductions[0],
skip_connect=(i != 0),
downsample=False,
norm_cfg=norm_cfg,
act_cfg=act_cfg) # CG block
)
cur_channels[0] = filters[0]
cur_channels[0] += in_ch
self.norm_prelu_0 = nn.Sequential(
build_norm_layer(cur_channels[0]),
nn.PReLU(cur_channels[0]))
# stage 1
self.level1 = nn.ModuleList()
for i in range(num_blocks[1]):
self.level1.append(
ContextGuidedBlock(
cur_channels[0] if i == 0 else filters[1],
filters[1], dilations[1], reductions[1],
downsample=(i == 0),
norm_cfg=norm_cfg,
act_cfg=act_cfg)) # CG block
cur_channels[1] = 2 * filters[1] + in_ch
self.norm_prelu_1 = nn.Sequential(
build_norm_layer(cur_channels[1]),
nn.PReLU(cur_channels[1]))
# stage 2
self.level2 = nn.ModuleList()
for i in range(num_blocks[2]):
self.level2.append(
ContextGuidedBlock(
cur_channels[1] if i == 0 else filters[2],
filters[2], dilations[2], reductions[2],
downsample=(i == 0),
norm_cfg=norm_cfg,
act_cfg=act_cfg)) # CG block
cur_channels[2] = 2 * filters[2]
self.norm_prelu_2 = nn.Sequential(
build_norm_layer(cur_channels[2]),
nn.PReLU(cur_channels[2]))
# stage 3
self.level3 = nn.ModuleList()
for i in range(num_blocks[3]):
self.level3.append(
ContextGuidedBlock(
cur_channels[2] if i == 0 else filters[3],
filters[3], dilations[3], reductions[3],
downsample=(i == 0),
norm_cfg=norm_cfg,
act_cfg=act_cfg)) # CG block
cur_channels[3] = 2 * filters[3]
self.norm_prelu_3 = nn.Sequential(
build_norm_layer(cur_channels[3]),
nn.PReLU(cur_channels[3]))
def forward(self, x):
# x = torch.cat([xA, xB], dim=0)
# stage 0
inp_2x = x # self.inject_2x(x)
inp_4x = self.inject_2x(x)
for layer in self.stem:
x = layer(x)
x = self.norm_prelu_0(torch.cat([x, inp_2x], 1))
x0_0A, x0_0B = x[:x.shape[0] // 2, :, :, :], x[x.shape[0] // 2:, :, :, :]
# stage 1
for i, layer in enumerate(self.level1):
x = layer(x)
if i == 0:
down1 = x
x = self.norm_prelu_1(torch.cat([x, down1, inp_4x], 1))
x1_0A, x1_0B = x[:x.shape[0] // 2, :, :, :], x[x.shape[0] // 2:, :, :, :]
# stage 2
for i, layer in enumerate(self.level2):
x = layer(x)
if i == 0:
down1 = x
x = self.norm_prelu_2(torch.cat([x, down1], 1))
x2_0A, x2_0B = x[:x.shape[0] // 2, :, :, :], x[x.shape[0] // 2:, :, :, :]
# stage 3
for i, layer in enumerate(self.level3):
x = layer(x)
if i == 0:
down1 = x
x = self.norm_prelu_3(torch.cat([x, down1], 1))
x3_0A, x3_0B = x[:x.shape[0] // 2, :, :, :], x[x.shape[0] // 2:, :, :, :]
return [x0_0A, x0_0B, x1_0A, x1_0B, x2_0A, x2_0B, x3_0A, x3_0B]
class InputInjection(nn.Module):
"""Downsampling module for CGNet."""
def __init__(self, num_downsampling):
super(InputInjection, self).__init__()
self.pool = nn.ModuleList()
for i in range(num_downsampling):
self.pool.append(nn.AvgPool2d(3, stride=2, padding=1))
def forward(self, x):
for pool in self.pool:
x = pool(x)
return x
def build_norm_layer(ch):
layer = nn.BatchNorm2d(ch, eps=0.01)
for param in layer.parameters():
param.requires_grad = True
return layer
diffFPN
class diffFPN(nn.Module):
def __init__(self, cur_channels=None, mid_ch=None,
dilations=None, reductions=None,
bilinear=True):
super(diffFPN, self).__init__()
# lateral convs for unifing channels
self.lateral_convs = nn.ModuleList()
for i in range(4):
self.lateral_convs.append(
cgblock(cur_channels[i] * 2, mid_ch * 2 ** i, dilations[i], reductions[i])
)
# top_down_convs
self.top_down_convs = nn.ModuleList()
for i in range(3, 0, -1):
self.top_down_convs.append(
cgblock(mid_ch * 2 ** i, mid_ch * 2 ** (i - 1), dilation=dilations[i], reduction=reductions[i])
)
# diff convs
self.diff_convs = nn.ModuleList()
for i in range(3):
self.diff_convs.append(
cgblock(mid_ch * (3 * 2 ** i), mid_ch * 2 ** i, dilations[i], reductions[i])
)
for i in range(2):
self.diff_convs.append(
cgblock(mid_ch * (3 * 2 ** i), mid_ch * 2 ** i, dilations[i], reductions[i])
)
self.diff_convs.append(
cgblock(mid_ch * 3, mid_ch * 2,
dilation=dilations[0], reduction=reductions[0])
)
self.up2x = up(32, bilinear)
def forward(self, output):
tmp = [self.lateral_convs[i](torch.cat([output[i * 2], output[i * 2 + 1]], dim=1))
for i in range(4)]
# top_down_path
for i in range(3, 0, -1):
tmp[i - 1] += self.up2x(self.top_down_convs[3 - i](tmp[i]))
# x0_1
tmp = [self.diff_convs[i](torch.cat([tmp[i], self.up2x(tmp[i + 1])], dim=1)) for i in [0, 1, 2]]
x0_1 = tmp[0]
# x0_2
tmp = [self.diff_convs[i](torch.cat([tmp[i - 3], self.up2x(tmp[i - 2])], dim=1)) for i in [3, 4]]
x0_2 = tmp[0]
# x0_3
x0_3 = self.diff_convs[5](torch.cat([tmp[0], self.up2x(tmp[1])], dim=1))
return x0_1, x0_2, x0_3
LSNet_diffFPN
class LSNet_diffFPN(nn.Module):
# SNUNet-CD with ECAM
def __init__(self, in_ch=3, mid_ch=32, out_ch=2, bilinear=True):
super(LSNet_diffFPN, self).__init__()
torch.nn.Module.dump_patches = True
n1 = 32 # the initial number of channels of feature map
filters = (n1, n1 * 2, n1 * 4, n1 * 8, n1 * 16)
num_blocks = (3, 3, 8, 12)
dilations = (1, 2, 4, 8)
reductions = (4, 8, 16, 32)
cur_channels = [0, 0, 0, 0]
cur_channels[0] = in_ch
self.backbone = light_siamese_backbone(in_ch=in_ch, num_blocks=num_blocks,
cur_channels=cur_channels,
filters=filters, dilations=dilations,
reductions=reductions)
self.head = cam_head(mid_ch=mid_ch,out_ch=out_ch)
self.FPN = diffFPN(cur_channels=cur_channels, mid_ch=mid_ch,
dilations=dilations, reductions=reductions, bilinear=bilinear)
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
def forward(self, x, debug=False):
output = self.backbone(x)
x0_1, x0_2, x0_3 = self.FPN(output)
out = self.head(x0_1, x0_2, x0_3)
if debug:
print_flops_params(self.backbone, [x], 'backbone')
print_flops_params(self.FPN, [output], 'diffFPN')
print_flops_params(self.head, [x0_1, x0_2, x0_3], 'head')
return (x0_1, x0_2, x0_3, x0_3, out,)
Mentions de copyright
Auteur de cet article [M0 61899108],Réimpression s’il vous plaît apporter le lien vers l’original, merci
https://fra.chowdera.com/2022/135/202205142322539306.html
Recommandé par sidebar
- Erreur de résolution de régression logique: valueerror: Solver lbfgs support only 'L2' or 'none' Penalties, got L1 penalty.
- Oracle OCI Computing, Storage, Network Tools designed to reduce Cloud Complexity
- Journal de bord du projet go [11e mise à jour du projet de la Décennie open source]
- Variables et opérateurs de script Shell
- Parler et trouver un emploi
- C'est la capacité, c'est la culture.
- Tensorflow Learning notes (5)
- Vitest prend en charge le workaround de cjs (scénario commun JS du produit Typescript)
- La réinstallabilité et l'équité des serrures de verrouillage dans les séries de programmation simultanées
- Discussion sur la relation entre Fiori Fundamentals et SAP ui5 Web Components
Devinez que vous aimez
RAM / FIFO Learning Review
La dernière version de 2022 est la version industrielle et commerciale ERP M7 V22. 0 version réseau du logiciel de gestion de la production financière pour l'achat, la vente et le stockage - système de gestion de la fabrication de groupe dans le cloud
[apprentissage automatique 05] régression Lasso et elasticnet
Raccourci idea
Recherche sur la création de fenêtres modales et non modales
[test de performance] chapitre 5 | installation de l'environnement jmeter
Guide d'utilisation de matplotlib, 100 cas du début à la fin! (code source joint)
Dots + Interval stats and geoms
Sigir2022 | recommandation de session basée sur les préférences des utilisateurs en matière de prix et d'intérêts
Cloudreve auto - construit Cloud disk Real station: la capacité et la vitesse sont déterminées par vous - même
Recommandé au hasard
- Construire un pool d'agents gratuits en utilisant la fonction Tencent Cloud
- Installation de redis et types de données de base
- Effet du graphique de rotation JS, mise en œuvre progressive de la transparence
- [stack + deep First Search] Bracket issue Summary
- Notes chapitre 1 Flux et fichiers (6) lecture aléatoire des fichiers et lecture zip des fichiers
- Votre base de données porte - t - elle vraiment un gilet pare - balles?
- Expérience 4 synchronisation et communication des processus
- Leetcode Tencent Selected Practice 50 questions - 557. Inverser le mot III dans la chaîne
- Questions de simulation complètes (y compris les réponses et l'analyse) pour l'Ingénieur en gestion de projet de l'intégration du système d'examen souple
- Cette API Alibaba TENCENT est utilisée pour gérer les artefacts et résoudre les problèmes de documentation
- La base théorique la plus solide du micro - service peut être considérée comme une excellente méthode mentale
- L'Octo, en tant que cadre de communication de service de haute performance du Groupe, peut - il être considéré comme un atout?
- Interview immersive: MySQL Serial gun, combien pouvez - vous combattre?
- Alibaba a demandé: quels modèles de limitation de courant les systèmes de l'entreprise ont - ils utilisés auparavant?
- Différences entre les logiciels ERP tels que faster software, Kingdee Software, UFIDA software, majordome software, dingjie Software et les logiciels d'importation et de vente
- P1439 [modèle] sous - séquence publique la plus longue
- Base de données MySQL (8): type de données - décimale
- Un homme de 38 ans qui vivait seul est mort.
- [freertos Task Recovery and pending]
- UDS - Comment réaliser la demande et la réponse du Service de diagnostic dans CAPL
- UDS - Comment implémenter la lecture du DTC et de son état dans CAPL
- Copier intelligemment tous les fichiers dans plusieurs dossiers à l'emplacement spécifié
- Clip vidéo, ajout de sous - titres SRT à une période de temps de la vidéo
- [SQL Union operator]
- Explication des principes de base des reptiles
- Huawei Device configure un VLAN Multicast Multi - à Multi - fonctions basé sur le VLAN utilisateur
- Copier la liste liée avec un pointeur aléatoire < facteur de difficulté>
- Quels sont les éléments exonérés de l'impôt sur le revenu des particuliers?
- NPM warn read shrinkwrap this version of NPM is compatible with [email protected] , mais package lock.
- Comment gérer la confidentialité des sources
- JVM (XVII) - - chargement du Code octet et de la classe (II) - - ensemble d'instructions du Code octet
- Anglais niveau 6 vocabulaire à haute fréquence sténographie + 2 décembre 2018 audition jour 04
- Configuration optimisée par ordinateur - win10
- Innovation Workshop Li Kaifu: la tendance la plus prometteuse de la Décennie est la technologie médicale
- Comprendre rapidement le CDN en mandarin
- L'apprentissage par petits échantillons n'est - il qu'une question d'auto - Salut universitaire?
- Déclarations communes à la base de données
- Learnopengl Learning Notes - Advanced Data
- La fonction de base de données interroge la base de données MySQL est un problème de temps correct
- Comment créer un nouveau menu en clic droit sous win10 en utilisant typora. Fichier MD