Theorie in die Praxis umsetzen: Anwendungen der Bildverarbeitung im maschinellen Lernen | von John Solomon Legara | Juni 2023

0
23


In diesem siebten Blogbeitrag setzen wir unsere Erkenntnisse aus früheren Sitzungen in die Tat um, indem wir einen Blattklassifizierungsalgorithmus entwickeln, eine Anwendung der Bildverarbeitung beim maschinellen Lernen. Diese Übung vermittelte uns ein umfassendes Verständnis des Ablaufs, von der Bildaufnahme bis zum Modelltraining.

Unser Ziel struggle es, eine Pipeline für maschinelles Lernen für einen Datensatz mit Bildern von Blättern verschiedener Klassen aufzubauen. Diese Pipeline umfasste mehrere Phasen: Lesen und Bereinigen der Bilder, Segmentieren der interessierenden Objekte, Extrahieren von Merkmalen aus diesen Objekten und schließlich das Trainieren eines Modells für maschinelles Lernen. Die Übung verdeutlichte, dass jede Part miteinander verbunden ist und dass die Effizienz einer einzelnen Part Auswirkungen auf die Genauigkeit des endgültigen Modells haben kann.

  1. Datenreinigung

Für die Datenbereinigungsphase habe ich das entwickelt parse_leaf Funktion. Diese Funktion liest ein Bild aus einer Datei, wandelt es in Graustufen um, wendet Otsus Schwellenwert für die Binarisierung an und beschriftet schließlich verbundene Regionen mithilfe morphologischer Operationen. Der Schwellenwert für Otsus Methode wird auf 60 % des Originals angepasst, um bessere Ergebnisse zu erzielen. Bei der angewandten morphologischen Operation handelt es sich um eine binäre Öffnung mit einem scheibenförmigen Strukturierungselement mit einem Radius von 3, die bei der Rauschunterdrückung und dem Füllen von Löchern hilft.

2. Segmentierung

Um einzelne Blätter aus den Bildern zu isolieren, habe ich beschriftete verbundene Regionen und Regionprops verwendet. Bereiche, die kleiner als ein angegebener Schwellenwert (standardmäßig 5000 Pixel) sind, werden verworfen, während die größeren als Blätter behandelt werden. Nach diesem Vorgang wird jedes Blatt in ein einzelnes Binärbild zerlegt.

def parse_leaf(image_path,
adjust_otsu=0.6,
region_thresh=5000,
plot=True,
save=False):
"""
This perform parses a picture of a leaf, isolates particular person
leaves from it, and returns them as separate photographs.

Parameters:
image_path (str): Relative path to the picture file (with respect
to the "leaves/" listing).
adjust_otsu (float): Otsu's thresholding adjustment issue.
Default is 0.6.
region_thresh (int): The minimal space in pixels for a area to
be thought-about a leaf. Default is 5000.
plot (bool): Whether or not to plot the person leaves or not. Default
is True.
save (bool): Whether or not to avoid wasting the plotted photographs or not. This parameter
just isn't used at present within the perform. Default is False.

Returns:
final_leaves (listing): An inventory of remoted leaf photographs. Every picture is a
2D numpy array, with every pixel being both True (for leaf) or
False (for background).
"""

# Load the picture
path = "leaves/"
picture = imread(os.path.be part of(path, image_path))

# Convert the picture to grayscale
gray_image = rgb2gray(picture)

# Preprocess the picture (e.g., apply thresholding)
binary_image = gray_image > threshold_otsu(gray_image) * adjust_otsu

# Invert the binary picture
binary_image = np.invert(binary_image)

selem = disk(3)
binary_image = binary_opening(binary_image, selem)

# Label related areas
labeled_image = label(binary_image)

# Discover leaf areas
leaf_regions = []
for area in regionprops(labeled_image):
# Exclude small areas (modify the edge as wanted)
if area.space > region_thresh:
leaf_regions.append(area)

dim = 6
exes = dim if len(leaf_regions) > dim else len(leaf_regions)
methods = len(leaf_regions)//dim + (1 if len(leaf_regions)%dim != 0 else 0)
if plot:
fig, ax = plt.subplots(methods, exes, figsize=(methods*5, exes*5))

final_leaves = []

for i, area in enumerate(leaf_regions):
minr, minc, maxr, maxc = area.bbox
leaf_image = labeled_image[minr:maxr, minc:maxc]

# Assuming leaf_image is the numpy array containing the picture information
unique_values, value_counts = np.distinctive(leaf_image, return_counts=True)

# Kind the distinctive values based mostly on their counts in descending order
sorted_indices = np.argsort(-value_counts)
sorted_unique_values = unique_values[sorted_indices]

final_leaf = leaf_image == sorted_unique_values[0]

if final_leaf[0, 0] == True and final_leaf[0, -1] == True:
final_leaf = np.invert(final_leaf)

if plot:
if methods > 1:
ax[i//dim, i%dim].imshow(final_leaf)
ax[i//dim, i%dim].axis('off')
else:
ax[i].imshow(final_leaf)
ax[i].axis('off')

final_leaves.append(final_leaf)

if plot and len(final_leaves) < exes * methods:
for i in vary(len(final_leaves), exes * methods):
ax[i//dim, i%dim].axis('off')

return final_leaves

3. Merkmalsextraktion

In der nächsten Part unserer Blattklassifizierungsübung haben wir uns mit der Merkmalsextraktion befasst. Wir haben aus jedem segmentierten Blattbild mehrere Eigenschaften extrahiert, um den Funktionsumfang für unser maschinelles Lernmodell zu bilden.

Wir haben die Funktion genutzt create_regionprops_tabledas die verwendet regionprops_table Funktion aus dem skimage.measure Modul zur Berechnung einer Vielzahl von Formdeskriptoren. Diese Deskriptoren sind für die Erkennung und Unterscheidung der Blätter unerlässlich.

Die extrahierten Eigenschaften lauten wie folgt:

A. „convex_area“: Die Anzahl der Pixel im konvexen Hüllenbild, dem kleinsten konvexen Polygon, das den interessierenden Bereich umschließt.

B. ‚Bereich‘: Die tatsächliche Anzahl der Pixel im interessierenden Bereich.

C. „Exzentrizität“: Die Exzentrizität der Ellipse, die die gleichen zweiten Momente wie die Area hat – ein Wert näher bei 0 bedeutet, dass ein Objekt kreisförmiger ist.

D. ‚Ausdehnung‘: Das Verhältnis der Regionsfläche zur Fläche des Begrenzungsrahmens.

e. ‚major_axis_length‘: Die Länge der Hauptachse der Ellipse, die dem interessierenden Bereich entspricht.

F. ‚minor_axis_length‘: Die Länge der Nebenachse der Ellipse, die dem interessierenden Bereich entspricht.

G. „Umfang“: Die Gesamtentfernung um den Rand des interessierenden Bereichs.

H. „Solidität“: Das Verhältnis der Pixel in der Area zu den Pixeln des konvexen Hüllenbildes.

ich. „Ausrichtung“: Der Winkel zwischen der x-Achse und der Hauptachse der Area.

J. ‚moments_central‘: Zentrale Momente bis zur dritten Ordnung. Es liefert Informationen über die Bildhelligkeit, den Schwerpunkt, die Ausrichtung usw.

ok. ‚moments_hu‘: Satz von sieben Zahlen, die gegenüber Verschiebungen, Drehungen und Skalierungsänderungen unveränderlich sind. Es ist hilfreich bei der Formanpassung.

l. ‚euler_number‘: Dies ist die Anzahl der Objekte in der Area abzüglich der Anzahl der Löcher in diesen Objekten.

M. ‚equivalent_diameter‘: Der Durchmesser eines Kreises mit der gleichen Fläche wie die Area.

Mit diesem Funktionsumfang konnten wir die primären Formmerkmale der Blätter erfassen.

Nachdem wir diese Merkmale für jedes Blatt extrahiert hatten, erstellten wir einen Datenrahmen für jede Blattklasse und beschrifteten ihn mit dem entsprechenden Klassennamen. Schließlich haben wir alle diese Datenrahmen zu einem zusammengeführt, der unseren vollständigen Datensatz für das Coaching des maschinellen Lernmodells bildet.

Die wichtigste Erkenntnis aus dieser Übung ist, dass die Bildmerkmalsextraktion ein entscheidender Schritt in der Pipeline für maschinelles Lernen ist, da sie Rohbilddaten in strukturierte Merkmale umwandelt, die zum Trainieren eines Modells für maschinelles Lernen verwendet werden können. Es ist wichtig, Merkmale auszuwählen, die die wichtigsten Merkmale der interessierenden Objekte, in diesem Fall der Blätter, erfassen können.

def create_regionprops_table(list_leaves, group):

properties = ('convex_area', 'space', 'eccentricity',
'extent', 'major_axis_length',
'minor_axis_length', 'perimeter',
'solidity', 'orientation',
'moments_central', 'moments_hu',
'euler_number', 'equivalent_diameter')

areas = []
for leaf in list_leaves:
data = regionprops_table(
label(leaf), leaf, properties
)
for key in data:
data[key] = data[key][0]
areas.append(data)
closing = pd.DataFrame(areas)
closing['label'] = group
return closing

df = pd.DataFrame()
for file in os.listdir(path):
if file == 'plantD.jpg':
adjust_otsu = 0.75
region_thresh = 700
elif file == 'plantC.jpg':
adjust_otsu = 0.6
region_thresh = 2000
else:
adjust_otsu = 0.6
region_thresh = 5000
leaves = parse_leaf(file,
plot=False,
region_thresh=region_thresh,
adjust_otsu=adjust_otsu)
df = pd.concat([df, create_regionprops_table(leaves, file[5])])
df.reset_index(inplace=True, drop=True)

4. Modell des maschinellen Lernens:

Der Weg zur Erstellung eines Modells für maschinelles Lernen begann mit der Aufteilung des Datensatzes in Trainings- und Testteilmengen. Der Trainingssatz belegte 75 % der Daten, während der Testsatz die restlichen 25 % enthielt. Die Stratifizierungsoption stellte sicher, dass bei der Aufteilung die ursprüngliche Klassenverteilung in beiden Sätzen beibehalten wurde.

Um das beste Modell zu finden, wurde eine Vielzahl von Algorithmen für maschinelles Lernen getestet. Es wurde eine Pipeline eingerichtet, die mit einem StandardScaler zur Standardisierung der Funktionen begann, gefolgt vom Klassifikator. In der Klassifikatorphase wurden verschiedene Modelle ausprobiert, darunter KNeighborsClassifier, LogisticRegression, SVC, DecisionTreeClassifier, RandomForestClassifier und GradientBoostingClassifier. Die Hyperparameter für jedes Modell wurden mithilfe eines Rastersuchansatzes mit geschichteter 5-facher Kreuzvalidierung optimiert.

seed = 34

X = df.drop(columns=['label']).to_numpy()
y = df['label'].to_numpy()

X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.25,
random_state=seed,
stratify=y)

def train_classification_model(X_train, y_train, X_test, y_test):
"""
This perform trains a classification mannequin utilizing grid
search to search out the perfect parameters for various classifiers.
It prints out the perfect mannequin, its parameters, classification
report, and check accuracy.

Parameters:
X_train (array-like): Function matrix for the coaching set.
y_train (array-like): Labels for the coaching set.
X_test (array-like): Function matrix for the check set.
y_test (array-like): Labels for the check set.

Returns:
best_model (sklearn estimator): The mannequin that achieved the
highest rating within the grid search.
predictions (array-like): Predictions made by the perfect mannequin
on the check set.
"""

pipeline = Pipeline([
('scaler', StandardScaler()),
('classifier', DecisionTreeClassifier(random_state=seed))
])

param_grid = [
{
'classifier': [KNeighborsClassifier()],
'classifier__n_neighbors': [3, 5, 10, 15]
},
{
'classifier': [LogisticRegression(solver='saga',
max_iter=10_000,
random_state=seed)],
'classifier__penalty': ['l1', 'l2'],
'classifier__C': [0.1, 1, 10]
},
{
'classifier': [SVC(random_state=seed)],
'classifier__kernel': ['linear', 'rbf', 'poly'],
'classifier__C': [0.1, 1, 10]
},
{
'classifier': [DecisionTreeClassifier(random_state=seed)],
'classifier__max_depth': [3, 5, 7]
},
{
'classifier': [RandomForestClassifier(random_state=seed)],
'classifier__n_estimators': [50, 100, 200],
'classifier__max_depth': [3, 5, 7]
},
{
'classifier': [GradientBoostingClassifier(random_state=seed)],
'classifier__n_estimators': [50, 100, 200],
'classifier__max_depth': [3, 5, 7]
}
]

grid_search = GridSearchCV(pipeline,
param_grid=param_grid,
cv=StratifiedKFold(n_splits=5),
verbose=1)

grid_search.match(X_train, y_train)

best_model = grid_search.best_estimator_
predictions = best_model.predict(X_test)

print("Greatest Mannequin:")
print(best_model)
print("nBest Mannequin Parameters:")
print(grid_search.best_params_)

print("nClassification Report:")
print(classification_report(predictions, y_test))
accuracy = np.imply(predictions == y_test) * 100
print(f"Check Accuracy: {accuracy:.2f}%")

return best_model, predictions

Die Klassifizierer lieferten sich einen harten Wettbewerb, aber das Modell mit der höchsten Punktzahl kristallisierte sich nach der strengen Rastersuche heraus. Die Particulars dieses Modells wurden zusammen mit seinen abgestimmten Parametern enthüllt. Darüber hinaus wurde ein Klassifizierungsbericht erstellt, der die Präzision, den Rückruf und den F1-Rating für jede Klasse zusammenfasst und so einen umfassenden Überblick über die Leistung des Modells bietet. Darüber hinaus wurde für den Testsatz ein Genauigkeitswert berechnet, um die Wirksamkeit des Modells zu validieren.

best_model, predictions = train_classification_model(
X_train,
y_train,
X_test,
y_test
)
# Create a brand new determine with a selected dimension
fig, ax = plt.subplots(figsize=(12, 12)) # Alter the scale as wanted

# Plot confusion matrix on the created axes
plot_confusion_matrix(best_model, X_test, y_test, ax=ax)

plt.present()

Darüber hinaus wurde ein SHAP-Wasserfalldiagramm (SHapley Additive exPlanations) in das Modell integriert, um die Bedeutung der Merkmale zu ermitteln. Es zeigte sich, dass das Merkmal „moments_hu-1“ die kritischste Determinante struggle, dicht gefolgt von „major_axis_length“. Diese Erkenntnisse können dazu beitragen, das Function-Engineering in zukünftigen Iterationen zu verfeinern und die Vorhersagegenauigkeit des Modells zu erhöhen.

Das gekrönte Modell zeigte außergewöhnliche Fähigkeiten und erreichte eine Testgenauigkeit von 92,73 %. Angesichts des Proportion Probability Criterion (PCC) von etwa 21 % und des 1,25-fachen PCC von etwa 27 % struggle es offensichtlich, dass die Vorhersagen des Modells die zufälligen Schätzungen deutlich übertrafen. Die hohe Genauigkeit beweist, dass das Modell intestine aus den Trainingsdaten lernt und das Potenzial für zuverlässige Vorhersagen auf ähnlichen, unbekannten Daten hat.

Somit wurde die Machine-Studying-Pipeline effektiv ausgeführt und eine solide Grundlage für zukünftige Blattklassifizierungsaufgaben geschaffen.

Abschluss

Zusammenfassend lässt sich sagen, dass diese Übung die Integration von Bildverarbeitung und maschinellem Lernen erfolgreich demonstriert hat, was zu einem effektiven Blattklassifizierungsmodell führte. Dieses Modell erreichte eine beeindruckende Genauigkeit von 92,73 %, wobei „moments_hu-1“ und „major_axis_length“ die wichtigsten einflussreichen Merkmale waren. Während die Leistung des Modells lobenswert ist, wurde in der Übung der iterative Charakter des Aufbaus einer Pipeline für maschinelles Lernen hervorgehoben und die Bedeutung jeder Part von der Bildvorverarbeitung bis zur Modellauswahl hervorgehoben. Das Potenzial für weitere Verbesserungen und die Anwendung dieser Methoden in komplexeren Szenarien machen dieses Gebiet zu einem vielversprechenden Forschungsgebiet.



Source link

HINTERLASSEN SIE EINE ANTWORT

Please enter your comment!
Please enter your name here