Tutorial: Automatisierte visuelle Überprüfung mithilfe von Transferlernen mit der ML.NET-Bildklassifizierungs-API
Erfahren Sie, wie Sie ein benutzerdefiniertes Deep-Learning-Modell mithilfe von Transferlernen, einem vorab trainierten TensorFlow-Modell und der ML.NET-Bildklassifizierungs-API trainieren, um Bilder von Betonoberflächen als gerissen oder nicht gerissen zu klassifizieren.
In diesem Tutorial lernen Sie, wie die folgenden Aufgaben ausgeführt werden:
- Das Problem verstehen
- Informationen zur ML.NET-Bildklassifizierungs-API
- Grundlegendes zum vorab trainierten Modell
- Trainieren eines benutzerdefinierten TensorFlow-Bildklassifizierungsmodells mithilfe von Transferlernen
- Klassifizieren von Bildern mit dem benutzerdefinierten Modell
Voraussetzungen
Beispielübersicht zur Bildklassifizierung mit Transferlernen
Bei diesem Beispiel handelt es sich um eine C#.NET Core-Konsolenanwendung, die Bilder mit einem vorab mit Deep Learning trainierten TensorFlow-Modell klassifiziert. Den Code für dieses Beispiel finden Sie im Beispielbrowser.
Das Problem verstehen
Bildklassifizierung ist ein Problem des maschinellen Sehens. Bei der Bildklassifizierung wird ein Bild eingegeben, das dann in eine bestimmte Klasse eingeordnet wird. Bildklassifizierungsmodelle werden häufig mit Deep Learning und neuronalen Netzwerken trainiert. Weitere Informationen finden Sie unter Deep Learning im Vergleich zu maschinellem Lernen.
Die Bildklassifizierung kann zum Beispiel in diesen Szenarios hilfreich sein:
- Gesichtserkennung
- Emotionserkennung
- Medizinische Diagnose
- Orientierungspunkterkennung
In diesem Tutorial wird ein benutzerdefiniertes Bildklassifizierungsmodell trainiert, um eine automatisierte visuelle Überprüfung von Brückenbelägen durchzuführen, bei der durch Risse unterbrochene Strukturen identifiziert werden.
ML.NET-Bildklassifizierungs-API
ML.NET bietet verschiedene Methoden zum Durchführen einer Bildklassifizierung. In diesem Tutorial wird die Methode des Transferlernens unter Verwendung der Bildklassifizierungs-API angewendet. Die Bildklassifizierungs-API nutzt TensorFlow.NET, eine Low-Level-Bibliothek, die C#-Bindungen für die TensorFlow-C++-API bereitstellt.
Was ist Übertragungslernen?
Beim Transferlernen werden Erkenntnisse aus der Lösung eines Problems für ein anderes verwandtes Problem genutzt.
Das von Grund auf neue Trainieren eines Deep-Learning-Modells erfordert das Festlegen mehrerer Parameter, zahlreiche bezeichnete Trainingsdaten und eine große Menge an Computeressourcen (Hunderte von GPU-Stunden). Die Verwendung eines vorab trainierten Modells zusammen mit dem Transferlernen ermöglicht es Ihnen, den Trainingsprozess zu verkürzen.
Trainingsprozess
Die Bildklassifizierungs-API startet den Trainingsprozess, indem das vorab trainierte TensorFlow-Modell geladen wird. Der Trainingsprozess setzt sich aus zwei Schritten zusammen:
- Engpassphase
- Trainingsphase
Engpassphase
Während der Engpassphase werden die Trainingsbilder geladen, wobei die Pixelwerte als Eingabe dienen, oder aber Features für die fixierten Ebenen des vorab trainierten Modells. Die fixierten Ebenen umfassen sämtliche Ebenen im neuronalen Netz bis hin zur vorletzte Ebene, die inoffiziell auch als Engpassebene bezeichnet wird. Diese Ebenen werden „fixiert“ genannt, da für diese kein Training stattfindet und Vorgänge lediglich weitergegeben werden. In diesen fixierten Ebenen werden die zugrunde liegenden Muster berechnet, anhand derer ein Modell zwischen den verschiedenen Klassen unterscheidet. Je mehr Ebenen es gibt, desto rechenintensiver ist dieser Schritt. Da es sich hierbei um eine einmalige Berechnung handelt, können die Ergebnisse zwischengespeichert und in späteren Durchläufen verwendet werden, wenn mit verschiedenen Parametern experimentiert wird.
Trainingsphase
Sobald die Ausgabewerte aus der Engpassphase berechnet sind, dienen sie als Eingabe für das nochmalige Training der letzten Ebene des Modells. Dieser Prozess ist iterativ und wird so oft ausgeführt, wie durch Modellparameter angegeben ist. Bei jeder Ausführung werden Verlust und Genauigkeit ausgewertet. Anschließend werden die entsprechenden Anpassungen zur Verbesserung des Modells vorgenommen, um so den Verlust zu minimieren und die Genauigkeit zu maximieren. Nach Abschluss des Trainings verfügen Sie über zwei Modellformate. Eines wird als .pb
-Version des Modells und das andere als für ML.NET serialisierte .zip
-Version des Modells bezeichnet. Für die Arbeit in von ML.NET unterstützten Umgebungen wird die .zip
-Version des Modells empfohlen. In Umgebungen, in denen ML.NET nicht unterstützt wird, haben Sie jedoch die Möglichkeit, die .pb
-Version zu verwenden.
Grundlegendes zum vorab trainierten Modell
Das in diesem Tutorial verwendete vorab trainierte Modell ist die 101-Ebenen-Variante des Modells „Residual Network (ResNet) v2“. Das Originalmodell ist darauf trainiert, Bilder in tausend Kategorien einzuteilen. Das Modell verwendet ein Bild der Größe 224 × 224 als Eingabe und gibt die Klassenwahrscheinlichkeiten für jede der Klassen aus, für die es trainiert ist. Ein Teil dieses Modells wird verwendet, um ein neues Modell mit benutzerdefinierten Bildern zu trainieren, damit dieses Vorhersagen für zwei Klassen treffen kann.
Erstellen einer Konsolenanwendung
Nachdem Sie nun grundlegende Kenntnisse über das Transferlernen und die Bildklassifizierungs-API haben, ist es an der Zeit, die Anwendung zu erstellen.
Erstellen Sie eine C#-Konsolenanwendung namens „DeepLearning_ImageClassification_Binary“. Klicken Sie auf die Schaltfläche Weiter.
Wählen Sie .NET 6 als zu verwendendes Framework aus. Klicken Sie auf die Schaltfläche Erstellen .
Installieren Sie das NuGet-Paket Microsoft.ML:
Hinweis
In diesem Beispiel wird, sofern nicht anders angegeben, die neueste stabile Version der genannten NuGet-Pakete verwendet.
- Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie NuGet-Pakete verwalten aus.
- Wählen Sie als Paketquelle „nuget.org“ aus.
- Wählen Sie die Registerkarte Durchsuchen aus.
- Aktivieren Sie das Kontrollkästchen Vorabversion einbeziehen.
- Suchen Sie nach Microsoft.ML.
- Wählen Sie die Schaltfläche Installieren aus.
- Wählen Sie die Schaltfläche OK im Dialogfeld Vorschau der Änderungen und dann die Schaltfläche Ich stimme zu im Dialogfeld Zustimmung zur Lizenz aus, wenn Sie den Lizenzbedingungen für die aufgelisteten Pakete zustimmen.
- Wiederholen Sie diese Schritte für die NuGet-Pakete Microsoft.ML.Vision, SciSharp.TensorFlow.Redist Version 2.3.1 und Microsoft.ML.ImageAnalytics.
Vorbereiten und Verstehen der Daten
Hinweis
Die Datasets für dieses Tutorial stammen von Marc Maguire, Sattar Dorafshan und Robert J. Thomas, „SDNET2018: A concrete crack image dataset for machine learning applications“ (2018). Durchsuchen Sie alle Datasets. Dokument 48. https://digitalcommons.usu.edu/all_datasets/48
SDNET2018 ist ein Bilddataset, das Anmerkungen für gerissene und nicht gerissene Betonstrukturen (Brückenbeläge, Mauern und Gehwege) enthält.
Die Daten sind in drei Unterverzeichnissen organisiert:
- D enthält Bilder von Brückenbelägen
- P enthält Bilder von Gehwegen
- W enthält Bilder von Mauern
Jedes dieser Unterverzeichnisse enthält zwei zusätzliche Unterverzeichnisse mit Präfixen:
- C ist das Präfix für gerissene Oberflächen
- U ist das Präfix für nicht gerissene Oberflächen
In diesem Tutorial werden ausschließlich Bilder von Brückenbelägen verwendet.
- Laden Sie das Dataset herunter, und entpacken Sie es.
- Erstellen Sie in Ihrem Projekt ein Verzeichnis mit dem Namen „assets“, um darin die Datasetdateien zu speichern.
- Kopieren Sie die Unterverzeichnisse CD und UD aus dem zuletzt entpackten Verzeichnis in das Verzeichnis assets.
Erstellen von Eingabe- und Ausgabeklassen
Öffnen Sie die Datei Program.cs, und ersetzen Sie die vorhandenen
using
-Anweisungen am Anfang der Datei durch die folgenden Anweisungen:using System; using System.Collections.Generic; using System.Linq; using System.IO; using Microsoft.ML; using static Microsoft.ML.DataOperationsCatalog; using Microsoft.ML.Vision;
Erstellen Sie in der Datei Program.cs unter der
Program
-Klasse eine Klasse mit dem NamenImageData
. Diese Klasse wird verwendet, um die ursprünglich geladenen Daten darzustellen.class ImageData { public string ImagePath { get; set; } public string Label { get; set; } }
ImageData
enthält die folgenden Eigenschaften:ImagePath
ist der vollqualifizierte Pfad, in dem das Bild gespeichert ist.Label
ist die Kategorie, zu der das Bild gehört. Dies ist der vorherzusagende Wert.
Erstellen Sie Klassen für Ihre Eingabe- und Ausgabedaten.
Definieren Sie unter der
ImageData
-Klasse das Schema Ihrer Eingabedaten in einer neuen Klasse namensModelInput
.class ModelInput { public byte[] Image { get; set; } public UInt32 LabelAsKey { get; set; } public string ImagePath { get; set; } public string Label { get; set; } }
ModelInput
enthält die folgenden Eigenschaften:Image
ist diebyte[]
-Darstellung des Bilds. Bei dem Modell wird erwartet, dass Bilddaten diesen Typ für das Training aufweisen.LabelAsKey
ist die numerische Darstellung vonLabel
.ImagePath
ist der vollqualifizierte Pfad, in dem das Bild gespeichert ist.Label
ist die Kategorie, zu der das Bild gehört. Dies ist der vorherzusagende Wert.
Nur
Image
undLabelAsKey
werden verwendet, um das Modell zu trainieren und Vorhersagen zu treffen. Die EigenschaftenImagePath
undLabel
werden beibehalten, damit einfacher auf den Namen und die Kategorie der ursprünglichen Bilddatei zugegriffen werden kann.Anschließend definieren Sie unter der
ModelInput
-Klasse das Schema Ihrer Ausgabedaten in einer neuen Klasse namensModelOutput
.class ModelOutput { public string ImagePath { get; set; } public string Label { get; set; } public string PredictedLabel { get; set; } }
ModelOutput
enthält die folgenden Eigenschaften:ImagePath
ist der vollqualifizierte Pfad, in dem das Bild gespeichert ist.Label
ist die ursprüngliche Kategorie, zu der das Bild gehört. Dies ist der vorherzusagende Wert.PredictedLabel
ist der vom Modell vorhergesagte Wert.
Ähnlich wie bei
ModelInput
ist nurPredictedLabel
für Vorhersagen erforderlich, da dies die vom Modell getroffene Vorhersage enthält. Die EigenschaftenImagePath
undLabel
werden beibehalten, damit einfacher auf den Namen und die Kategorie der ursprünglichen Bilddatei zugegriffen werden kann.
Erstellen eines Arbeitsbereichsverzeichnisses
Wenn sich Trainings-und Validierungsdaten nicht häufig ändern, empfiehlt es sich, die berechneten Engpasswerte für weitere Ausführungen zwischenzuspeichern.
- Erstellen Sie in Ihrem Projekt ein neues Verzeichnis namens workspace, um die berechneten Engpasswerte und die
.pb
-Version des Modells zu speichern.
Definieren von Pfaden und Initialisieren von Variablen
Definieren Sie unter den using-Anweisungen den Speicherort Ihrer Ressourcen, der berechneten Engpasswerte und der
.pb
-Version des Modells.var projectDirectory = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "../../../")); var workspaceRelativePath = Path.Combine(projectDirectory, "workspace"); var assetsRelativePath = Path.Combine(projectDirectory, "assets");
Initialisieren Sie die
mlContext
-Variable mit einer neuen Instanz von MLContext.MLContext mlContext = new MLContext();
Die MLContext-Klasse ist der Startpunkt für alle ML.NET-Vorgänge. Durch das Initialisieren von MLContext wird eine neue ML.NET-Umgebung erstellt, die für mehrere Objekte des Modellerstellungsworkflows verwendet werden kann. Die Klasse ähnelt dem Konzept von
DbContext
in Entity Framework.
Laden der Daten
Erstellen einer Hilfsmethode zum Laden von Daten
Die Bilder werden in zwei Unterverzeichnissen gespeichert. Vor dem Laden der Daten müssen diese in eine Liste mit ImageData
-Objekten formatiert werden. Erstellen Sie dazu die LoadImagesFromDirectory
-Methode auf.
IEnumerable<ImageData> LoadImagesFromDirectory(string folder, bool useFolderNameAsLabel = true)
{
}
Fügen Sie in
LoadImagesFromDirectory
den folgenden Code hinzu, um alle Dateipfade aus den Unterverzeichnissen abzurufen:var files = Directory.GetFiles(folder, "*", searchOption: SearchOption.AllDirectories);
Durchlaufen Sie dann die einzelnen Dateien mithilfe einer
foreach
-Anweisung.foreach (var file in files) { }
Überprüfen Sie, ob in der
foreach
-Anweisung die Dateierweiterungen unterstützt werden. Die Bildklassifizierungs-API unterstützt JPEG- und PNG-Formate.if ((Path.GetExtension(file) != ".jpg") && (Path.GetExtension(file) != ".png")) continue;
Rufen Sie anschließend die Bezeichnung für die Datei ab. Wenn der
useFolderNameAsLabel
-Parameter auftrue
festgelegt ist, wird das übergeordnete Verzeichnis, in dem die Datei gespeichert wird, als Bezeichnung verwendet. Andernfalls wird erwartet, dass die Bezeichnung ein Präfix des Dateinamens oder der Dateiname selbst ist.var label = Path.GetFileName(file); if (useFolderNameAsLabel) label = Directory.GetParent(file).Name; else { for (int index = 0; index < label.Length; index++) { if (!char.IsLetter(label[index])) { label = label.Substring(0, index); break; } } }
Abschließend erstellen Sie eine neue Instanz von
ModelInput
.yield return new ImageData() { ImagePath = file, Label = label };
Vorbereiten der Daten
Rufen Sie die
LoadImagesFromDirectory
-Hilfsmethode auf, um die Liste der Bilder abzurufen, die nach der Initialisierung dermlContext
-Variablen für das Training verwendet werden.IEnumerable<ImageData> images = LoadImagesFromDirectory(folder: assetsRelativePath, useFolderNameAsLabel: true);
Laden Sie dann die Bilder mithilfe der
LoadFromEnumerable
-Methode in eineIDataView
-Schnittstelle.IDataView imageData = mlContext.Data.LoadFromEnumerable(images);
Die Daten werden in der Reihenfolge geladen, in der sie aus den Verzeichnissen gelesen wurden. Um die Daten auszugleichen, mischen Sie sie zufällig mithilfe der
ShuffleRows
-Methode.IDataView shuffledData = mlContext.Data.ShuffleRows(imageData);
Bei Modellen für maschinelles Lernen wird eine Eingabe im numerischen Format erwartet. Daher muss vor dem Training eine Vorverarbeitung der Daten durchgeführt werden. Erstellen Sie eine
EstimatorChain
, die ausMapValueToKey
undLoadRawImageBytes
-Transformationen besteht. DieMapValueToKey
-Transformation übernimmt den kategorischen Wert aus der SpalteLabel
, konvertiert diesen in einen numerischenKeyType
-Wert und speichert ihn in einer neuen Spalte namensLabelAsKey
.LoadImages
greift auf Werte aus der SpalteImagePath
zusammen mit dem ParameterimageFolder
zu, um Bilder für das Training zu laden.var preprocessingPipeline = mlContext.Transforms.Conversion.MapValueToKey( inputColumnName: "Label", outputColumnName: "LabelAsKey") .Append(mlContext.Transforms.LoadRawImageBytes( outputColumnName: "Image", imageFolder: assetsRelativePath, inputColumnName: "ImagePath"));
Verwenden Sie die
Fit
-Methode, um die Daten auf diepreprocessingPipeline
EstimatorChain
gefolgt von derTransform
-Methode anzuwenden, wodurch eineIDataView
zurückgegeben wird, die die vorverarbeiteten Daten enthält.IDataView preProcessedData = preprocessingPipeline .Fit(shuffledData) .Transform(shuffledData);
Beim Trainieren eines Modells ist es wichtig, sowohl über ein Trainingsdataset als auch ein Validierungsdataset zu verfügen. Das Modell wird mit dem Trainingsset trainiert. Wie gut es Vorhersagen über unbekannte Daten erstellt, wird an der Leistung im Vergleich zum Validierungsset gemessen. Basierend auf den Ergebnissen dieser Leistung nimmt das Modell Anpassungen an dem Gelernten vor, um die Ergebnisse zu verbessern. Das Validierungsset kann entweder aus der Aufteilung des ursprünglichen Datasets oder aus einer anderen Quelle stammen, die bereits für diesen Zweck vorgesehen ist. In diesem Fall wird das vorverarbeitete Datenset in Trainings-, Validierungs- und Testsets unterteilt.
TrainTestData trainSplit = mlContext.Data.TrainTestSplit(data: preProcessedData, testFraction: 0.3); TrainTestData validationTestSplit = mlContext.Data.TrainTestSplit(trainSplit.TestSet);
Im obigen Codebeispiel werden zwei Aufteilungen vorgenommen. Zunächst werden die vorverarbeiteten Daten aufgeteilt, wobei 70% für das Training und die restlichen 30% für die Validierung verwendet werden. Anschließend werden die 30% des Validierungssets weiter in Validierungs- und Testsets unterteilt, wobei 90% für die Validierung und 10% für Tests verwendet werden.
Ein gutes Beispiel, um den Sinn und Zweck dieser Datenaufteilungen zu verstehen, ist eine Prüfungsituation. Wenn Sie für eine Prüfung lernen, lesen Sie Ihre Notizen, Bücher oder andere Unterlagen, um die in der Prüfung enthaltenen Themen zu lernen und zu vertiefen. Dafür ist das Trainingsset da. Dann können Sie eine Probeklausur ablegen, um Ihren Wissensstand zu überprüfen. Hier bietet sich das Validierungsset an. Sie möchten vor der eigentlichen Prüfung feststellen, ob Sie die Inhalte richtig verstanden haben. Ausgehend von den Ergebnissen können Sie herausfinden, was Sie falsch gemacht bzw. nicht richtig verstanden haben, und so die Ergebnisse in den Lernprozess für die eigentliche Prüfung einbeziehen. Zum Schluss legen Sie die Prüfung ab. Dafür wird das Testset verwendet. Sie haben die Fragen in der Prüfung noch nie gesehen und nutzen zur Bearbeitung der vorliegenden Aufgabe nun das, was Sie sich durch den Lernprozess (Training) und die Überprüfung des Gelernten (Validierung) angeeignet haben.
Ordnen Sie den Teilbereichen die jeweiligen Werte für die Trainings-, Validierungs- und Testdaten zu.
IDataView trainSet = trainSplit.TrainSet; IDataView validationSet = validationTestSplit.TrainSet; IDataView testSet = validationTestSplit.TestSet;
Definieren der Trainingspipeline
Das Modelltraining umfasst mehrere Schritte. Zunächst wird die Bildklassifizierungs-API verwendet, um das Modell zu trainieren. Anschließend werden die verschlüsselten Bezeichnungen in der Spalte PredictedLabel
mithilfe der MapKeyToValue
-Transformation wieder in ihren ursprünglichen kategorischen Wert konvertiert.
Erstellen Sie eine neue Variable, um einen Satz erforderlicher und optionaler Parameter für ein ImageClassificationTrainer-Element zu speichern.
var classifierOptions = new ImageClassificationTrainer.Options() { FeatureColumnName = "Image", LabelColumnName = "LabelAsKey", ValidationSet = validationSet, Arch = ImageClassificationTrainer.Architecture.ResnetV2101, MetricsCallback = (metrics) => Console.WriteLine(metrics), TestOnTrainSet = false, ReuseTrainSetBottleneckCachedValues = true, ReuseValidationSetBottleneckCachedValues = true };
Ein ImageClassificationTrainer-Element nimmt mehrere optionale Parameter an:
FeatureColumnName
ist die Spalte, die als Eingabe für das Modell verwendet wird.LabelColumnName
ist die Spalte für den vorherzusagenden Wert.ValidationSet
ist dieIDataView
-Schnittstelle, die die Validierungsdaten enthält.Arch
definiert, welche der vorab trainierten Modellarchitekturen verwendet werden soll. In diesem Tutorial wird die 101-Ebenen-Variante des Modells „ResNetv2“ verwendet.MetricsCallback
verknüpft eine Funktion, um den Fortschritt während des Trainings zu verfolgen.TestOnTrainSet
weist das Modell an, die Leistung anhand des Trainingssets zu messen, wenn kein Validierungsset vorhanden ist.ReuseTrainSetBottleneckCachedValues
informiert das Modell, ob die zwischengespeicherten Werte aus der Engpassphase in nachfolgenden Durchläufen verwendet werden sollen. Die Engpassphase ist eine einmalige Pass-Through-Berechnung, die bei der ersten Durchführung sehr rechenintensiv ist. Wenn sich die Trainingsdaten nicht ändern, und Sie mit einer anderen Anzahl von Epochen oder anderen Batchgrößen experimentieren möchten, können Sie mit den zwischengespeicherten Werten den Zeitaufwand für das Training eines Modells erheblich verringern.ReuseValidationSetBottleneckCachedValues
ist vergleichbar mitReuseTrainSetBottleneckCachedValues
, allerdings handelt es sich in diesem Fall um das Validierungsdataset.WorkspacePath
definiert das Verzeichnis, in dem die berechneten Engpasswerte und die.pb
-Version des Modells gespeichert werden sollen.
Definieren Sie die
EstimatorChain
-Trainingspipeline, die ausmapLabelEstimator
und ImageClassificationTrainer besteht.var trainingPipeline = mlContext.MulticlassClassification.Trainers.ImageClassification(classifierOptions) .Append(mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel"));
Verwenden Sie die Methode
Fit
, um Ihr Modell zu trainieren.ITransformer trainedModel = trainingPipeline.Fit(trainSet);
Verwenden des Modells
Nachdem Sie Ihr Modell trainiert haben, ist es an der Zeit, es zur Klassifizierung von Bildern zu verwenden.
Erstellen Sie eine neue Hilfsmethode namens OutputPrediction
, um Vorhersageinformationen in der Konsole anzuzeigen.
private static void OutputPrediction(ModelOutput prediction)
{
string imageName = Path.GetFileName(prediction.ImagePath);
Console.WriteLine($"Image: {imageName} | Actual Value: {prediction.Label} | Predicted Value: {prediction.PredictedLabel}");
}
Klassifizieren eines einzelnen Bilds
Erstellen Sie eine neue Methode namens
ClassifySingleImage
, um eine Einzelbildvorhersage zu erstellen und auszugeben.void ClassifySingleImage(MLContext mlContext, IDataView data, ITransformer trainedModel) { }
Erstellen Sie eine
PredictionEngine
-Klasse innerhalb derClassifySingleImage
-Methode. DiePredictionEngine
-Klasse ist eine praktische API, mit der Sie eine Vorhersage für eine einzelne Dateninstanz übergeben und dann ausführen können.PredictionEngine<ModelInput, ModelOutput> predictionEngine = mlContext.Model.CreatePredictionEngine<ModelInput, ModelOutput>(trainedModel);
Um auf eine einzelne
ModelInput
-Instanz zuzugreifen, konvertieren Sie diedata
IDataView
in eineIEnumerable
mit derCreateEnumerable
-Methode und erhalten Sie dann das erste Ergebnis.ModelInput image = mlContext.Data.CreateEnumerable<ModelInput>(data,reuseRowObject:true).First();
Verwenden Sie die
Predict
-Methode, um das Bild zu klassifizieren.ModelOutput prediction = predictionEngine.Predict(image);
Geben Sie die Vorhersage mit der
OutputPrediction
-Methode in der Konsole aus.Console.WriteLine("Classifying single image"); OutputPrediction(prediction);
Rufen Sie
ClassifySingleImage
unter dem Aufruf derFit
-Methode mithilfe des Testsets der Bilder auf.ClassifySingleImage(mlContext, testSet, trainedModel);
Klassifizieren mehrerer Bilder
Fügen Sie eine neue Methode namens
ClassifyImages
unter derClassifySingleImage
-Methode hinzu, um mehrere Bildvorhersagen zu erstellen und auszugeben.void ClassifyImages(MLContext mlContext, IDataView data, ITransformer trainedModel) { }
Erstellen Sie mithilfe der
Transform
-Methode eineIDataView
-Schnittstelle, die die Vorhersagen enthält. Fügen Sie derClassifyImages
-Methode den folgenden Code hinzu.IDataView predictionData = trainedModel.Transform(data);
Zur Iteration über die Vorhersagen konvertieren Sie die
predictionData
IDataView
in eineIEnumerable
mithilfe derCreateEnumerable
-Methode und erhalten Sie dann die ersten zehn Ergebnisse.IEnumerable<ModelOutput> predictions = mlContext.Data.CreateEnumerable<ModelOutput>(predictionData, reuseRowObject: true).Take(10);
Iterieren Sie die ursprünglichen und vorhergesagten Bezeichnungen für die Vorhersagen, und geben Sie sie aus.
Console.WriteLine("Classifying multiple images"); foreach (var prediction in predictions) { OutputPrediction(prediction); }
Rufen Sie schließlich
ClassifyImages
unter derClassifySingleImage()
-Methode mithilfe des Testsets der Bilder auf.ClassifyImages(mlContext, testSet, trainedModel);
Ausführen der Anwendung
Führen Sie die Konsolenanwendung aus. Die Ausgabe sollte in etwa wie folgt aussehen. Möglicherweise werden Warnungen oder Verarbeitungsnachrichten angezeigt. Diese wurden jedoch aus Gründen der Übersichtlichkeit aus den folgenden Ergebnissen entfernt. Aus Gründen der Kürze wurde die Ausgabe komprimiert.
Engpassphase
Für den Bildnamen wird kein Wert ausgegeben, da die Bilder als byte[]
geladen werden, sodass kein Bildname angezeigt werden kann.
Phase: Bottleneck Computation, Dataset used: Train, Image Index: 279
Phase: Bottleneck Computation, Dataset used: Train, Image Index: 280
Phase: Bottleneck Computation, Dataset used: Validation, Image Index: 1
Phase: Bottleneck Computation, Dataset used: Validation, Image Index: 2
Trainingsphase
Phase: Training, Dataset used: Validation, Batch Processed Count: 6, Epoch: 21, Accuracy: 0.6797619
Phase: Training, Dataset used: Validation, Batch Processed Count: 6, Epoch: 22, Accuracy: 0.7642857
Phase: Training, Dataset used: Validation, Batch Processed Count: 6, Epoch: 23, Accuracy: 0.7916667
Klassifizieren der Ausgabe von Bildern
Classifying single image
Image: 7001-220.jpg | Actual Value: UD | Predicted Value: UD
Classifying multiple images
Image: 7001-220.jpg | Actual Value: UD | Predicted Value: UD
Image: 7001-163.jpg | Actual Value: UD | Predicted Value: UD
Image: 7001-210.jpg | Actual Value: UD | Predicted Value: UD
Bei der Überprüfung des Bilds 7001-220.jpg können Sie feststellen, dass tatsächlich kein Riss zu sehen ist.
Herzlichen Glückwunsch! Sie haben ein Deep-Learning-Modell zur Klassifizierung von Bildern erstellt.
Verbessern des Modells
Wenn Sie mit den Ergebnissen des Modells nicht zufrieden sind, können Sie versuchen, seine Leistung zu verbessern, indem Sie einige der folgenden Ansätze ausprobieren:
- Mehr Daten: Je mehr Beispiele vorhanden sind, von denen ein Modell lernt, desto besser ist dessen Leistung. Laden Sie das vollständige SDNET2018-Dataset herunter, und verwenden Sie es für das Training.
- Erweitern der Daten: Eine gängige Technik, um eine größere Datenvielfalt zu erreichen, ist die Erweiterung der Daten durch Aufnahme eines Bilds und Anwendung verschiedener Transformationen (Drehen, Spiegeln, Verschieben, Zuschneiden). Auf diese Weise erhalten Sie verschiedene Beispiele, von denen das Modell lernen kann.
- Längere Trainingsdauer: Umso länger die Trainingsdauer, desto genauer werden die Ergebnisse des Modells sein. Durch die Erhöhung der Anzahl von Epochen kann sich die Leistung des Modell erheblich verbessern.
- Experimentieren mit Hyperparametern: Zusätzlich zu den in diesem Tutorial verwendeten Parametern können weitere Parameter angepasst werden, um die Leistung zu steigern. Die Änderung des Lerntempos, das den Umfang der Aktualisierungen am Modell nach jeder Epoche bestimmt, kann zu einer höheren Leistung führen.
- Verwenden einer anderen Modellarchitektur: Abhängig von der Beschaffenheit Ihrer Daten kann sich das Modell, das am besten deren Merkmale erlernen kann, unterscheiden. Wenn Sie mit der Leistung Ihres Modells unzufrieden sind, sollten Sie versuchen, die Architektur zu ändern.
Nächste Schritte
In diesem Tutorial haben Sie erfahren, wie Sie ein benutzerdefiniertes Deep-Learning-Modell mithilfe von Transferlernen, einem vorab trainierten TensorFlow-Modell und der ML.NET-Bildklassifizierungs-API erstellen, um Bilder von Betonoberflächen als gerissen oder nicht gerissen zu klassifizieren.
Fahren Sie mit dem nächsten Tutorial fort, um mehr zu erfahren.