Main Content

Questa pagina si riferisce alla release precedente. La corrispondente pagina in inglese è stata rimossa nella release attuale.

Addestramento della rete di Deep Learning per classificare nuove immagini

Questo esempio mostra come utilizzare il transfer learning per riaddestrare una rete neurale convoluzionale, per classificare un nuovo set di immagini.

Le reti di classificazione delle immagini sono state addestrate su oltre un milione di immagini e sono in grado di classificare le immagini in 1000 categorie di oggetti ad esempio, tastiera, tazza da caffè, matita e molti animali. Le reti hanno appreso ricche rappresentazioni di feature per un’ampia gamma di immagini. La rete prende un’immagine come input e produce come output un’etichetta per l’oggetto all’interno dell’immagine, insieme alle probabilità che l’oggetto appartenga a ciascuna delle altre categorie di oggetti.

Il transfer learning è ampiamente utilizzato nelle applicazioni di Deep Learning. Si può prendere una rete preaddestrata e utilizzarla come punto di partenza per l’apprendimento di una nuova attività. Il fine-tuning di una rete con il transfer learning è di solito molto più rapido e semplice dell'addestramento di una rete da zero con pesi inizializzati in modo casuale. È possibile trasferire rapidamente le feature apprese a una nuova attività utilizzando un numero minore di immagini di addestramento.

Caricamento dei dati

Decomprimere e caricare le nuove immagini come un datastore di immagini. Questo set di dati molto piccolo contiene solo 75 immagini. Dividere i dati in set di dati di addestramento e di convalida. Utilizzare il 70% delle immagini per l’addestramento e il 30% per la convalida.

unzip('MerchData.zip');
imds = imageDatastore('MerchData', ...
    'IncludeSubfolders',true, ...
    'LabelSource','foldernames'); 
[imdsTrain,imdsValidation] = splitEachLabel(imds,0.7);

Caricamento della rete preaddestrata

Caricare una rete GoogLeNet preaddestrata. Se il pacchetto di supporto Deep Learning Toolbox™ Model for GoogLeNet Network non è installato, il software fornisce un link per il download.

Per provare una rete preaddestrata diversa, aprire questo esempio in MATLAB® e selezionare una rete differente. Ad esempio, si può provare squeezenet, una rete ancora più veloce di googlenet. È possibile eseguire questo esempio con altre reti preaddestrate. Per un elenco di tutte le reti disponibili, vedere Caricamento delle reti neurali preaddestrate.

net = googlenet;

Utilizzare analyzeNetwork per visualizzare una visualizzazione interattiva dell'architettura di rete e informazioni dettagliate sui livelli della rete.

analyzeNetwork(net)

Il primo elemento della proprietà Layers della rete corrisponde al livello di input dell’immagine. Per una rete GoogLeNet, questo livello richiede immagini di input di dimensioni 224x224x3, dove 3 è il numero di canali del colore. Altre reti possono richiedere immagini di input di dimensioni diverse. Ad esempio, la rete Xception richiede immagini di dimensioni 299x299x3.

net.Layers(1)
ans = 
  ImageInputLayer with properties:

                      Name: 'data'
                 InputSize: [224 224 3]

   Hyperparameters
          DataAugmentation: 'none'
             Normalization: 'zerocenter'
    NormalizationDimension: 'auto'
                      Mean: [224×224×3 single]

inputSize = net.Layers(1).InputSize;

Sostituzione dei livelli finali

I livelli convoluzionali della rete estraggono le feature dell'immagine che l'ultimo livello apprendibile e il livello di classificazione finale utilizzano per classificare l'immagine di input. Questi due livelli, 'loss3-classifier' e 'output' in GoogLeNet, contengono le informazioni su come combinare le feature estratte dalla rete in probabilità di classe, in un valore di perdita e in etichette previste. Per riaddestrare una rete preaddestrata alla classificazione di nuove immagini, sostituire questi due livelli con i nuovi livelli adattati al nuovo set di dati.

Convertire la rete addestrata in un grafico di livello.

lgraph = layerGraph(net);

Individuare i nomi dei due livelli da sostituire. È possibile eseguire questa operazione manualmente o utilizzare la funzione di supporto findLayersToReplace per identificare automaticamente questi livelli.

[learnableLayer,classLayer] = findLayersToReplace(lgraph);
[learnableLayer,classLayer] 
ans = 
  1×2 Layer array with layers:

     1   'loss3-classifier'   Fully Connected         1000 fully connected layer
     2   'output'             Classification Output   crossentropyex with 'tench' and 999 other classes

Nella maggior parte delle reti, l'ultimo livello con pesi apprendibili è un livello completamente connesso. Sostituire questo livello completamente connesso con un nuovo livello completamente connesso con un numero di output pari al numero di classi del nuovo set di dati (5, in questo esempio). In alcune reti, come SqueezeNet, l'ultimo livello apprendibile è invece un livello convoluzionale 1x1. In questo caso, sostituire il livello convoluzionale con un nuovo livello convoluzionale con un numero di filtri pari al numero di classi. Per apprendere più rapidamente nel nuovo livello rispetto ai livelli trasferiti, aumentare i fattori della velocità di apprendimento del livello.

numClasses = numel(categories(imdsTrain.Labels));

if isa(learnableLayer,'nnet.cnn.layer.FullyConnectedLayer')
    newLearnableLayer = fullyConnectedLayer(numClasses, ...
        'Name','new_fc', ...
        'WeightLearnRateFactor',10, ...
        'BiasLearnRateFactor',10);
    
elseif isa(learnableLayer,'nnet.cnn.layer.Convolution2DLayer')
    newLearnableLayer = convolution2dLayer(1,numClasses, ...
        'Name','new_conv', ...
        'WeightLearnRateFactor',10, ...
        'BiasLearnRateFactor',10);
end

lgraph = replaceLayer(lgraph,learnableLayer.Name,newLearnableLayer);

Il livello di classificazione specifica le classi di output della rete. Sostituire il livello di classificazione con uno nuovo senza etichette di classe. trainNetwork imposta automaticamente le classi di output del livello al momento dell'addestramento.

newClassLayer = classificationLayer('Name','new_classoutput');
lgraph = replaceLayer(lgraph,classLayer.Name,newClassLayer);

Per verificare che i nuovi livelli siano collegati correttamente, tracciare il grafico del nuovo livello e ingrandire gli ultimi livelli della rete.

figure('Units','normalized','Position',[0.3 0.3 0.4 0.4]);
plot(lgraph)
ylim([0,10])

Congelamento dei livelli iniziali

La rete ora è pronta per essere riaddestrata sul nuovo set di immagini. Opzionalmente, è possibile "congelare" i pesi dei livelli iniziali della rete, impostando la velocità di apprendimento di tali livelli su zero. Durante l’addestramento, trainNetwork non aggiorna i parametri dei livelli congelati. Poiché non è necessario calcolare i gradienti dei livelli congelati, il congelamento dei pesi di molti livelli iniziali può accelerare notevolmente l'addestramento della rete. Se il nuovo set di dati è piccolo, il congelamento dei livelli iniziali della rete può anche evitare l’overfitting di questi livelli sul nuovo set di dati.

Estrarre i livelli e le connessioni del grafico di livello e selezionare quali livelli congelare. In GoogLeNet, i primi 10 livelli costituiscono il "gambo" iniziale della rete. Utilizzare la funzione di supporto freezeWeights per impostare le velocità di apprendimento su zero nei primi 10 livelli. Utilizzare la funzione di supporto createLgraphUsingConnections per connettere nuovamente tutti i livelli nell'ordine originale. Il nuovo grafico di livello comprende gli stessi livelli, ma con le velocità di apprendimento dei livelli precedenti impostate su zero.

layers = lgraph.Layers;
connections = lgraph.Connections;

layers(1:10) = freezeWeights(layers(1:10));
lgraph = createLgraphUsingConnections(layers,connections);

Addestramento della rete

La rete richiede immagini di input di dimensioni 224x224x3, ma le immagini nel datastore di immagini hanno dimensioni diverse. Utilizzare un datastore di immagini aumentate per ridimensionare automaticamente le immagini di addestramento. Specificare ulteriori operazioni di aumento da eseguire sulle immagini di addestramento: capovolgere casualmente le immagini di addestramento lungo l'asse verticale e traslarle casualmente fino a 30 pixel e scalarle fino al 10% in orizzontale e verticale. L’aumento dei dati aiuta la rete ad evitare l’overfitting e a memorizzare i dettagli esatti delle immagini di addestramento.

pixelRange = [-30 30];
scaleRange = [0.9 1.1];
imageAugmenter = imageDataAugmenter( ...
    'RandXReflection',true, ...
    'RandXTranslation',pixelRange, ...
    'RandYTranslation',pixelRange, ...
    'RandXScale',scaleRange, ...
    'RandYScale',scaleRange);
augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain, ...
    'DataAugmentation',imageAugmenter);

Per ridimensionare automaticamente le immagini di convalida senza eseguire un ulteriore aumento dei dati, utilizzare un datastore di immagini aumentate senza specificare alcuna ulteriore operazione di pre-elaborazione.

augimdsValidation = augmentedImageDatastore(inputSize(1:2),imdsValidation);

Specificare le opzioni di addestramento. Impostare InitialLearnRate su un valore piccolo per rallentare l'apprendimento nei livelli trasferiti che non sono già congelati. Nel passaggio precedente, sono stati aumentati i fattori della velocità di apprendimento per l'ultimo livello apprendibile onde accelerare l'apprendimento nei nuovi livelli finali. Questa combinazione di impostazioni della velocità di apprendimento determina un apprendimento rapido nei nuovi livelli, un apprendimento più lento nei livelli intermedi e nessun apprendimento nei livelli precedenti congelati.

Specificare il numero di epoche per l’addestramento. Quando si esegue il transfer learning, non è necessario l’addestramento per un numero elevato di epoche. Un'epoca è un ciclo di addestramento completo sull'intero set di dati di addestramento. Specificare la dimensione del mini-batch e i dati di convalida. Calcolare la precisione della convalida una volta per ogni epoca.

miniBatchSize = 10;
valFrequency = floor(numel(augimdsTrain.Files)/miniBatchSize);
options = trainingOptions('sgdm', ...
    'MiniBatchSize',miniBatchSize, ...
    'MaxEpochs',6, ...
    'InitialLearnRate',3e-4, ...
    'Shuffle','every-epoch', ...
    'ValidationData',augimdsValidation, ...
    'ValidationFrequency',valFrequency, ...
    'Verbose',false, ...
    'Plots','training-progress');

Addestrare la rete utilizzando i dati di addestramento. Per impostazione predefinita, trainNetwork utilizza una GPU se è disponibile. Questo richiede Parallel Computing Toolbox™ e un dispositivo GPU supportato. Per informazioni sui dispositivi supportati, vedere GPU Computing Requirements (Parallel Computing Toolbox). In caso contrario, trainNetwork utilizza una CPU. Inoltre, si può specificare l’ambiente di esecuzione tramite l’argomento nome-valore dell’'ExecutionEnvironment' delle trainingOptions. Poiché il set di dati è così piccolo, l'addestramento è veloce.

net = trainNetwork(augimdsTrain,lgraph,options);

Classificazione delle immagini di convalida

Classificare le immagini di convalida utilizzando la rete ottimizzata e calcolare la precisione della classificazione.

[YPred,probs] = classify(net,augimdsValidation);
accuracy = mean(YPred == imdsValidation.Labels)
accuracy = 0.9000

Visualizzare quattro immagini di convalida di esempio con le etichette previste e le probabilità previste delle immagini con tali etichette.

idx = randperm(numel(imdsValidation.Files),4);
figure
for i = 1:4
    subplot(2,2,i)
    I = readimage(imdsValidation,idx(i));
    imshow(I)
    label = YPred(idx(i));
    title(string(label) + ", " + num2str(100*max(probs(idx(i),:)),3) + "%");
end

Riferimenti

[1] Szegedy, Christian, Wei Liu, Yangqing Jia, Pierre Sermanet, Scott Reed, Dragomir Anguelov, Dumitru Erhan, Vincent Vanhoucke, and Andrew Rabinovich. "Going deeper with convolutions." In Proceedings of the IEEE conference on computer vision and pattern recognition, pp. 1-9. 2015.

Vedi anche

| | | |

Argomenti complementari