Support Vector Machine (SVM)¶
Dieses Tutorial enthält die Support Vector Machine (SVM) -Technik zur Klassifizierung von Flussbettmorphologietypen als Funktion von Hydraulik- und Sedimenttransportdaten.
Enable interactive reading and executing code blocks with and find morphology-predictor-svm.ipynb Alternatively, install Python and JupyterLab locally and download this Jupyter notebook.
Theorie¶
In the field of restoration science, the identification of river morphology provides essential insights, for instance, to guide target terraforming aiming at re-instating a near-census natural state of a fluvial landscape. In addition, morphological pattern may serve as a predictor for estimating fluvial sediment transport and vice versa. Thus, there is a bidirectional relationship between fluvial hydraulics, sediment transport, and morphological pattern, which represent physical habitat for aquatic species and may even affect energy production Recking et al., 2016.
Yet, classifying and predicting fluvial morphodynamics is challenging because of the complexity of river ecosystems and every river being a unique environment. However,there are repeating morphological units of rivers with similar characteristics. A basic set of repetitive morphological features was introduced by Montgomery & Buffington (1997), and we will focus in this tutorial on the following five morphological units (click on the items to read more):
Diese morphologischen Einheiten können in der oben aufgeführten Reihenfolge entlang eines Flusses gefunden werden, beginnend an der Quelle und endend mit seiner Mündung. So können * Step Pool * Einheiten typischerweise im stromaufwärts gelegenen (Berg-) Flussabschnitt gefunden werden, während * Sandbetten * überwiegend in flacheren Flussabschnitten in der Nähe von Mündungen oder Zusammenflüssen vorhanden sind. Beachten Sie, dass es noch viele andere morphologische Einheiten gibt, wie z. B. Slackwater, Swale oder Bars Wyrick & Pasternack, 2014. Fig. Figure 1 illustriert einige morphologische Einheiten von natürlichen Flüssen nahe dem Zensus.

Figure 1:a) Ein kolluvialer Quellwasserstrom (Furtschaglbach, Österreich), b ein Kaskadenstrom (Torrent des Favrands, Frankreich), c ein Grundwasserstrom (Anse St-Jean, Québec, Kanada), d ein Stufenbeckenstrom (Dessoubre, Frankreich), e ein Planbettstrom (Dranse, Schweiz), f ein Rifflebeckenstrom (Le diable, Québec, Kanada), g ein Zopfstrom (Jenbach, Deutschland). Quelle: Schwindt (2017)
To guide restoration actions, experts often visually classify morphology units on-site, though some of them may also be distinguishable on aerial imagery. On-site (in-situ) expert assessments may also serve as ground truth for machine learning models. In this exercise, we will use hydrodynamic parameters with expert-based ground truth from the database https://
Vorverarbeitung¶
Lastdaten¶
We downloaded a dataset from https://
Jede Probe wird aus den Querschnitten von 146 verschiedenen Flüssen rund um den Globus abgeleitet.
Der Datensatz umfasst den hydraulischen und Sedimenttransport (z. B. Korngrößen), obwohl wir in diesem Tutorial nur die folgenden Parameter verwenden, um das SVM-Modell zu trainieren:
W: Kanalbreite (m)
S: Kanalneigung (m)
Q: Entlastung (ms)
U: Massenstromgeschwindigkeit (m s)
H: Wassertiefe (m)
In a machine learning context, these parameters for predicting morphological units are also called features. The first step is to load (and view) the data as a pandas.DataFrame:
import pandas as pd
data= pd.read_csv("data/bedload_dataset")
dataReinigen Sie den Dataset¶
Um zu vermeiden, dass das SVM-Modell durch Statiken beeinflusst wird, die auf Nonsense-Einträgen (z. B. Not-a-Number NaN) oder extremen Ausreißern basieren, die beispielsweise auf Tippfehlern beruhen, werden wir einige Reinigungsmethoden anwenden.
NaN-Werte entfernen¶
Der erste Reinigungsschritt besteht darin, NaNs zu entfernen, die das SVM-Modell später zu schlechten Schlussfolgerungen führen können.
# dataset essencial info
print(data.info(),"\n")
# remove rows that contains at least one NaN value
print(data.dropna(inplace=True))
# verify that all NaN values were removed
for column in data.columns.to_list():
print(column,":",data[column].isnull().any())
# verify final shape of the dataset
print(data.shape)<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1067 entries, 0 to 1066
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 W 1067 non-null float64
1 S 1067 non-null float64
2 Q 1067 non-null float64
3 U 1067 non-null float64
4 H 1067 non-null float64
5 Morphology 1067 non-null object
dtypes: float64(5), object(1)
memory usage: 50.1+ KB
None
None
W : False
S : False
Q : False
U : False
H : False
Morphology : False
(1067, 6)
Suchausreißer¶
Ausreißer können in extremen Umgebungen oder unter extremen Bedingungen auftreten (z. B. starke Niederschläge), aber einige von ihnen stammen auch aus Geräteausfällen, die die Leistung des SVM-Modells beeinträchtigen. Daher ist das Erkennen und Entfernen derartiger gerätebezogener Ausreißer ein wesentlicher Schritt.
Die Visualisierung der aufgetragenen Funktionen in einem Scatter-Plot kann hilfreich sein, um Ausreißerkandidaten zu erkennen. Der folgende Codeblock erstellt Streuplots von jedem Feature, markiert den Erwartungswert und den Abstand von 2 Standardabweichungen (unter der Annahme einer Gauß-ähnlichen Verteilung).
from mpl_toolkits.axes_grid1 import host_subplot
import mpl_toolkits.axisartist as AA
import numpy as np
import matplotlib.pyplot as plt
# visualize scatter of the features
host = host_subplot(111, axes_class=AA.Axes)
plt.subplots_adjust(right=0.75)
# plot visualization parameters
labels = data.columns[0:5].tolist()
colors = ["crimson", "purple", "limegreen", "gold", "blue"]
width=0.5
# iterate on features of the dataset (i.e. column names)
for i, l in enumerate(labels):
if i ==0:
ax = host
ax.set_ylabel(labels[i])
else:
ax = host.twinx()
new_fixed_axis = ax.get_grid_helper().new_fixed_axis
ax.axis["right"] = new_fixed_axis(loc="right",
axes=ax,
offset=(60*(i-1), 0))
ax.axis["right"].toggle(all=True)
ax.set_ylabel(labels[i])
x = np.ones(data.shape[0])*i + (np.random.rand(data.shape[0])*width-width/2.)
ax.scatter(x, data[data.columns[i]],color=colors[i])
mean = data[f"{data.columns[i]}"].mean()
std = np.std(data[data.columns[i]])
ax.plot([i-width/2., i+width/2.], [mean, mean], color="k")
ax.plot([i,i], [mean-2*std, mean+2*std], color="k")
ax.set_xticks(range(len(labels)))
ax.set_xticklabels(labels)
plt.draw()
plt.show()
Ausreißer entfernen¶
Ausreißer können mit zwei verschiedenen Methoden entfernt werden:
Handbuch (d. h. Expertenurteil): Identifizieren Sie Ausreißer der Merkmale und entfernen Sie sie, indem Sie Grenzen ihres Intervalls festlegen.
Automatisiert: Nehmen Sie eine Wahrscheinlichkeitsverteilung an und setzen Sie Grenzen basierend auf einer geringen Wahrscheinlichkeit des Beobachtungsereignisses.
Die folgenden Codeblöcke implementieren diese beiden Optionen (Manual-Experte und automatisierte) Methoden. Die manuelle Entfernung von Ausreißern ist hard codiert , da die Grenzen von Experten angegeben werden sollten.
The automated approach (below else statement) assumes the data having a Gaussian distribution, where points with a so-called z-score greater than 4 (four) are removed. Data points with a z-score less or equal to four have a 99.9%-chance of being inside an interval of four standard deviations away from the expected value. Thus, a sample that has a 0.01%-chance of occurrence is considered automatically an outlier and removed from the dataset. Thus, in this case, the z-score represents the standard deviation, and we use the zscore function of the scipy library.
from scipy.stats import zscore
# choose the method to remove outliers
# remove_method = "expert_analysis"
remove_method = "zscore"
if "expert" in remove_method:
data = data.loc[(data["qs"]<0.02) &
(data["Q"]<2000) &
(data["W"]<250)]
else:
data = data[(np.abs(zscore(data.loc[:,data.columns!="Morphology"])) < 4).all(axis=1)]
dataKlassenproportionen überprüfen¶
Ein Machine-Learning-Modell erfordert, dass die Ground Truth-Daten einem Qualitätsstandard entsprechen. Diese beinhalten (unter anderem):
Jede Kombination von Modellen benötigt eine andere Mindestanzahl von Stichproben statistische Signifikanz]. Es ist keine triviale Aufgabe, die Mindestanzahl von Proben zu identifizieren, die ein vertrauenswürdiges Modell ergeben. Um jedoch eine Klasse richtig darzustellen (was auch immer das bedeutet), muss die sogenannte Frequenzverteilung] jedes Merkmals der Population Frequenzverteilung] ähnlich sein.
Mehr als 30 Samples beim Umgang mit normal verteilten Variablen ist eine gute Faustregel.]
Idealerweise sollten die für ein Klassifizierungsproblem verwendeten Klassen durch eine ähnliche Probenmenge dargestellt werden. Ein unausgewogener Datensatz kann ein Modell erzeugen, das der korrekten Klassifizierung der Klasse mit einer größeren Anzahl von Stichproben den Vorzug gibt. Dies ist eine Folge der Verwendung von Genauigkeit als Leistungsmetrik. Genauigkeit ist das Verhältnis von korrekt und die Gesamtzahl der Vorhersagen (). Indem die Gesamtzahl der korrekten Vorhersagen einer ausgewogenen vorgezogen wird, maskiert die Genauigkeit die Wichtigkeit, die unterrepräsentierten Klassen korrekt zu erhalten.
Lösungen für den Ausgleich unausgeglichener Proben umfassen:
Sammeln oder Generieren neuer Daten (z. B. Methoden von Monte Carlo]. Wenn verfügbar, ist precision] für die Messung der Peformanz des Modells (statt der Genauigkeit) vorzuziehen.
Weighting Klassenmerkmale, was bedeutet, Gewichte zuzuweisen, um die Bedeutung unterrepräsentierter Klassen korrekt zu erhöhen.] Bei Klassifizierungsproblemen ergibt das Testen verschiedener Gewichtskombinationen eine ROC curve, die den Effekt unterschiedlicher Gewichte auf die Modellleistung zeigt].
In diesem Tutorial können die Proben als ausgewogen angesehen werden, mit Ausnahme der Sandbettklasse (siehe Ausgabe unten). Gewichtung und ROC-Kurven werden hier nicht berücksichtigt. Wenn Sensitivität und Spezifikation der Sandbettklasse bei der Klassifizierung von Testdaten akzeptabel wären, könnte das Modell auch für die Sandbettklassifizierung verwendet werden, ohne dass Abgleichtechniken verwendet werden müssten.
data["Morphology"].value_counts()Step-pool 247
Plane Bed 243
Riffle-pool 241
Braiding 228
Sand bed 79
Name: Morphology, dtype: int64Ableiten neuer Vorhersagen¶
Manchmal ist es möglich, aus den vorhandenen neue sinnvolle Features zu berechnen. Zum Beispiel bekannte Prädiktoren für Morphologie sind:
the product of (energy) slope (-), bulk flow velocity (m/s), and water depth (m), which basically represents shear stress
das Verhältnis von Entladung (m/s) und Breite (m) (dh Q/W)
import warnings
from pandas.core.common import SettingWithCopyWarning
warnings.simplefilter(action="ignore", category=SettingWithCopyWarning)
# compute new columns for the new features SUH and Q/W
data["SUH"] = (data.loc[:,"S"]*data.loc[:,"U"]*data.loc[:,"H"])
data["Q/W"] = (data.loc[:,"Q"]/data.loc[:,"W"])
dataMultikolinearität überprüfen¶
Korrelationsmerkmale (d. h. statistisch abhängige Messparameter) können zu unzuverlässigen Modellen führen. Betrachten Sie zum Beispiel einen Wissenschaftler, der maschinelles Lernen (ML) -Modelle verwenden möchte, um die Anzahl der Touristen vorherzusagen, die in Brasilien während ihres Urlaubs sonnenverbrannt werden. Sie möchte die Intensität der Sonnenstrahlung und die Anzahl der verkauften Eiswürfel als Features verwenden. Der Wissenschaftler kann feststellen, dass beide Merkmale relevant sind, um die Anzahl der sonnenverbrannten Touristen vorherzusagen, aber der Grund für diese Feststellung ist, dass die Anzahl der verkauften Eiswürfel und die Sonnenintensität korreliert sind. Daher hat der Wissenschaftler keine Möglichkeit zu wissen, was die wirkliche Bedeutung jedes Merkmals bei der Vorhersage sonnenverbrannter Touristen ist, da die Merkmale gleichzeitig wachsen und abnehmen. Übrigens haben Eiscremekonsum und Sonnenbrand keine Gemeinsamkeiten, aber das ist ein anderes Thema.
To this end, it is important to investigate the correlation among features and consider eliminating the correlated features to produce a more reliable model. One way to visually spot colinearity is plotting the combination of two variables in a scatter plot. For this purpose, the below figure aids in spotting the following aspects of the bedload_dataset:
There is a strong linear correlation between the and features.
Es gibt keine lineare Korrelation zwischen und .
The flow velocity distribuiton is approximately normal (see main diagonal).
import seaborn as sns
# plot scatter of the 2d (two dimensinal) combination of features
sns.pairplot(data.loc[:,data.columns!="Morphology"])
plt.show()
Darüber hinaus ist eine heatmap] eine weitere effiziente Methode, um lineare Korrelationen zwischen Merkmalen zu visualisieren. Auch die Berechnung linear correlation ermöglicht die quantitative Analyse.]
from seaborn import heatmap
# verify linear coorralation
feature_corr_df = data.loc[:,data.columns!="Morphology"].corr()
mask = np.zeros_like(feature_corr_df)
mask[np.triu_indices_from(mask)] = True
sns.heatmap(feature_corr_df,
annot=True, # print value inside the grid
mask=mask # mask values (boolean matrix)
)
Varianz-Inflationsfaktor (VIF)¶
Eine einfache Methode zur Bewertung multicollinerity] ist die Berechnung des Varianz-Inflationsfaktors (VIF) für jedes Merkmal, der die Korrelation zwischen den Merkmalen quantifiziert.
The first step to compute the VIF is treating a feature as a dependent variable and fit a linear regression model using the other features as independent variable. Second, store the corresponding mean square errors yielded by the linear model.
Schließlich kann VIF für jedes Merkmal durch die folgende Gleichung berechnet werden:
ist der Varianz-Inflationsfaktor des -Features, und
ist der mittlere quadratische Fehler, der sich aus der linearen Regression des -Features ergibt.
Beachten Sie, dass je kleiner das MSE (besseres lineares Regressionsmodell), desto größer ist die Inflation. Mit anderen Worten, große VIF-Werte weisen auf eine hohe Korrelation des betrachteten Merkmals mit mindestens einem der anderen Merkmale hin. Dennoch ist es nicht möglich, nur basierend auf VIF zu sagen, welches andere Feature VIF aufblasen lässt.
As rule of thumb, a VIF greater than 10 (ten) indicates an unsuitable set of features to produce a reliable ML model. Ideally, the VIF should remain smaller than 5 (five), which is considered moderate correlation Franke, 2010. However, these reference values are not a generally and always applicable rule. VIF equal to or greater than 10 can still yield a good model.
Weitere Analysen zur Untersuchung der Auswirkungen eines hohen VIF auf korrelierte Merkmale können durchgeführt werden, indem jedes Merkmal gleichzeitig entfernt wird und untersucht wird, wie sich die Merkmalsentfernung auf die Variation der Standardfehler und p-value] des Modells auswirkt.
In this tutorial, 2 features have a VIF 10 (notably, and ), as the following code block shows.
from sklearn.linear_model import LinearRegression
# compute VIF for the features
def calculate_vif(df, features):
vif, tolerance = {}, {}
for feature in features:
# extract all the other features you will regress against
X = [f for f in features if f != feature]
X, y = df[X], df[feature]
# extract r-squared from the fit
r2 = LinearRegression().fit(X, y).score(X, y)
# compute VIF
vif[feature] = 1 / (1 - r2)
# return VIF DataFrame
return pd.DataFrame({'VIF': vif})
# call fuction calculate_vif with features as input
calculate_vif(df=data,
features=data.columns[data.columns != "Morphology"].to_list())Features entfernen, um VIF zu reduzieren¶
With the goal of reducing the feature VIFs to less than 5, we use a trial-and-error approach in this tutorial. Modifying the below code block shows that removing and is enough to reduce the VIFs of the remaining features to less than 5. In particular, these two removed variables also go into above-introduced features and . Thus, although and are removed, they still “contribute information” to the final model.
Die Kombination korrelierter Merkmale, um eine neue zu erzeugen, und deren späteres Entfernen ist ein gängiger Ansatz, um VIFs zu reduzieren. Da wir durch das Entfernen einiger Merkmale gute VIF-Werte erzielt haben, ist keine weitere Analyse erforderlich.
Schließlich werden die Funktionen, die zum Trainieren und Testen des SVM-Modells verwendet werden, durch die Ausgabe des Codeblocks unten angezeigt.
# try and error approach removing features get VIFs < 10
data = data.loc[:, data.columns[(data.columns !="H")&
(data.columns !="Q")
]
]
# compute VIF again to verify if VIFs are less than 5
calculate_vif(df=data,
features=data.columns[data.columns != "Morphology"].to_list())Split Test- und Trainingsdatensätze¶
Der letzte Vorbereitungsschritt für die Erstellung des SVM-Modells besteht darin, aus dem gesamten bedload_dataset einen Trainings- und Testdatensatz abzuleiten. Die Auswahl einer Freigabe für Daten zum Zusammenstellen eines Trainings- und Testdatensatzes ist in der Regel eine heuristische Wahl. Hier verwenden wir 33% der Daten, um später eine endgültige Hypothese zu testen. Beachten Sie, dass innerhalb der geteilten Datensätze der Index der Samples (Zeilen der Tabellendaten) ihre entsprechende Klasse innerhalb der target-Datensätze hat.
from sklearn.model_selection import train_test_split
# split dataframes with features and labels only
labels = data.loc[:, "Morphology"]
predictors = data.loc[:, data.columns[data.columns != "Morphology"]]
# split testing set as 33% of the data
# X correspond to the featues (matrix form)
# y corresponf to the labels (vector form)
X_train, X_test, y_train, y_test = train_test_split(predictors,
labels,
test_size=0.3,
random_state=42 # seed for random selection of data
)
# visualize training and testing sets
print("TRAINING DATASET PREDICTORS")
print(X_train.head(), "\n")
print("dataframe size", X_train.shape,"\n")
print("------------------------------------------")
print("TRAINING DATASET TARGET")
print(y_train,"\n")
print()
print("------------------------------------------------------------------------------------\n")
print("TESTING DATASET PREDICTORS")
print(X_test.head())
print("dataframe size", X_test.shape,"\n")
print("------------------------------------------")
print("TESTING DATASET TARGET")
print(y_test.head())
print("Vector size", y_test.shape)
TRAINING DATASET PREDICTORS
W S U SUH Q/W
256 6.91 0.01100 1.02 0.003366 0.277858
397 88.09 0.00210 1.99 0.008149 3.889545
586 14.02 0.02070 1.34 0.022190 1.078459
526 218.00 0.00041 0.52 0.000175 0.541284
9 8.00 0.02000 1.18 0.007316 0.370000
dataframe size (726, 5)
------------------------------------------
TRAINING DATASET TARGET
256 Plane Bed
397 Plane Bed
586 Step-pool
526 Sand bed
9 Riffle-pool
...
89 Riffle-pool
337 Plane Bed
476 Plane Bed
123 Riffle-pool
876 Braiding
Name: Morphology, Length: 726, dtype: object
------------------------------------------------------------------------------------
TESTING DATASET PREDICTORS
W S U SUH Q/W
203 2.57 0.01040 1.58 0.008216 0.793774
937 105.00 0.00096 1.90 0.002918 3.076190
546 93.00 0.00050 1.10 0.001320 2.688172
214 53.04 0.00380 1.44 0.004596 1.211916
312 6.28 0.02020 0.34 0.001511 0.074841
dataframe size (312, 5)
------------------------------------------
TESTING DATASET TARGET
203 Riffle-pool
937 Braiding
546 Sand bed
214 Riffle-pool
312 Plane Bed
Name: Morphology, dtype: object
Vector size (312,)
Erstellen Sie das SVM-Modell¶
Arbeitsprinzip¶
Eine Support Vector Machine (SVM) ist ein Lernalgorithmus, der nach einer sogenannten hyperplane sucht, die Feature-Klassen optimal trennt. Um eine optimale Trennung zu finden, versucht der Algorithmus, die Entfernung (oder den Rand) von der Hyperebene zu den nächsten Datenpunkten zu maximieren. Die Datenpunkte nahe den Grenzen des Randes werden auch als Unterstützungsvektoren bezeichnet, da sie als Referenz auf draw die Hyperebene dienen (siehe Fig. Figure 2 unten).

Figure 2:Illustration einer Hyperebene und Ränder einer SVM. Quelle: Ricardo Barros
Nehmen wir zum Beispiel an, dass zwei der oben genannten Klassen linear trennbar sind. Wir können die Regionen, die jede Klasse enthalten, durch die folgende Hyperebene definieren:
--> Klasse Red , und --> Klasse Blau
wo
ist der Vektor der Gewichte,
ist die Matrix der Features,
ist die unabhängige Variable (auch bias genannt), und
Der Wert von 1 wird als repräsentative Vereinfachung gewählt, da grundsätzlich ein beliebiger Wert sein kann.
Schließlich (nach einigen Schritten, die hier nicht besprochen werden) können wir eine optimale Hyperebene berechnen, indem wir den folgenden Ausdruck minimieren:
Dabei ist der transponierte Gewichtsvektor.
In the real world, however, it is common to find problems where classes are not linearly separable. In such situations, so-called kernels can be applied. A kernel is a function that transforms to a matrix with higher dimensions by combining the available features to create new features (i.e., new dimensions).
Here, we apply the Radius Base Function (RBF) kernel. The RBF is a popular kernel because it transforms the into an infinite dimension matrix without the risk of overfitting the model.
k-fache Kreuzvalidierung¶
SVMs, die aus einem RBF-Kernel bestehen, können durch Abstimmung zweier Parameter validiert werden:
C : bestimmt, wie viel die Margen permissiv sind. Es unterscheidet zwischen einer **harten Marge ** (dh einer Marge, die eine geringe oder keine Penetration von Datenpunkten ermöglicht) und einer **weichen Marge ** (dh einer Marge, die eine Penetration von Datenpunkten innerhalb der Marge ermöglicht). Ein höheres C entspricht einem härteren Margin.
gamma : bestimmt die Ähnlichkeitsregion zwischen den Proben. Es ist die einzige Variable des RBF-Kernels. Je höher Gamma ist, desto breiter ist der Einfluss einer markierten Probe auf die Klassifizierung einer neuen Probe.
Harte Ränder können auch als die Sensibilität der Hyperebene beim Anpassen mit den Daten interpretiert werden. Je härter der Rand ist, desto mehr verdreht sich die Hyperebene, um keinen Datenpunkt in den Rand eindringen zu lassen.
In diesem Tutorial definieren wir C basierend auf einem Try-and-Error-Ansatz und einem Gamma, das aus einem fünffachen cross-validation] stammt. Der folgende Codeblock erstellt die SVM mithilfe der sklearn-Bibliothek und druckt die Validierungs- und Trainingsfehlerkurven aus, die sich aus unterschiedlichen gamma ergeben.
from sklearn.svm import SVC
from sklearn.model_selection import validation_curve
# define C, gamma range, kernel and number of cross-val. folds
gamma_range = np.logspace(-5, 3, 13)
C=500 # chosen hyperparameter through tunnig
kernel = "rbf" # radius base function
n_of_folds = 5
# Peform 5-fold cross-validation and save training and validation error
train_scores, test_scores = validation_curve(SVC(kernel=kernel,
C=C),
X_train,
y_train,
param_name="gamma",
param_range=gamma_range,
scoring="accuracy",
cv=n_of_folds
)
# convert accuracy into error
train_error = 1-train_scores
validation_error = 1-test_scores
# compute 5-fold cross-validation mean and std of error
train_error_mean = np.mean(train_error, axis=1)
train_error_std = np.std(train_error, axis=1)
validation_error_mean = np.mean(validation_error, axis=1)
validation_error_std = np.std(validation_error, axis=1)
#-------------------------------------------------------------------
# visualization of training and error validation
plt.title("Validation Curve with SVM")
plt.xlabel(r"$\gamma$")
plt.ylabel("Error (1-accuracy)")
plt.ylim(-0.01, 1.1)
lw = 2
plt.semilogx(
param_range, train_error_mean, label="Training error", color="darkorange", lw=lw
)
plt.fill_between(
param_range,
train_error_mean - train_error_std,
train_error_mean + train_error_std,
alpha=0.2,
color="darkorange",
lw=lw,
)
plt.semilogx(
param_range, validation_error_mean, label="Cross-validation error", color="navy", lw=lw
)
plt.fill_between(
param_range,
validation_error_mean - validation_error_std,
validation_error_mean + validation_error_std,
alpha=0.2,
color="navy",
lw=lw,
)
plt.legend(loc="best")
plt.show()
Wählen Sie optimale Parameter¶
Die Entscheidung über optimale Parameter für die SVM hängt von Ihrer Meinung ab. Zur Auswahl optimaler Parameter in diesem Tutorial quantifiziert der unten stehende Codeblock den oben gezeigten Plot (insbesondere die blaue Kurve) in tabellarischer Form und speichert den Gamma, der den kleinsten Fehler ergibt ( gamma opt ).
# save optimal gamma
index_min = min(range(len(validation_error_mean)), key=validation_error_mean.__getitem__)
validation_error_min = validation_error_mean[index_min]
gamma_opt = param_range[index_min] # gamma that gives minimun validation error
# visualize error evolution with gamma
columns = ["Mean validation error","gamma"]
array = np.array([validation_error_mean, param_range]).transpose()
print( pd.DataFrame(array,columns=columns), "\n")
print("Minimun mean validation error:", validation_error_min)
print("optimal gamma:", gamma_opt) Mean validation error gamma
0 0.575739 0.000010
1 0.524856 0.000046
2 0.471101 0.000215
3 0.446311 0.001000
4 0.388474 0.004642
5 0.341606 0.021544
6 0.294709 0.100000
7 0.254861 0.464159
8 0.318262 2.154435
9 0.391252 10.000000
10 0.409173 46.415888
11 0.515144 215.443469
12 0.637789 1000.000000
Minimun mean validation error: 0.2548606518658479
optimal gamma: 0.46415888336127725
Zugoptimale Hypothese SVM Modell¶
Nach der Definition eines Gamma, das den kleinsten Validierungsfehler ( gamma opt ) ergibt, können wir ein optimales Hypothesenmodell ( h opt ) für den gesamten Trainingsdatensatz trainieren. Darüber hinaus können wir die Genauigkeit des Modells bewerten, indem wir es zur Klassifizierung des Testdatensatzes verwenden. Der folgende Codeblock zeigt das Trainingsverfahren, die Anpassung der SVM (dh eine optimale Hypothese) und druckt die Punktzahl der optimalen Hypothese.
# train optimal model and evaluate accuracy
h_opt = SVC(kernel=kernel,
gamma=gamma_opt,
C=C) # instantiate optimal model
h_opt.fit(X_train,y_train) # train the model with entire training set
print("Error (1-Accuracy) of h_opt on testing data: \n -->>",1- h_opt.score(X_test,y_test)) Error (1-Accuracy) of h_opt on testing data:
-->> 0.19551282051282048
Leistungsbewertung (Konfusionsmatrix)¶
Schließlich erzeugt der folgende Codeblock die sogenannte confusion matrix, um die optimale Leistung des Hypothesenmodells bei der Klassifizierung der Proben mit unterschiedlichen Morphologien zu bewerten. Die Verwirrungsmatrix verwendet die Gesamtzahl der Proben und visualisiert ihre wahren und vorhergesagten morphologischen Einheiten.
from sklearn.metrics import plot_confusion_matrix
#plot confusion matrix
plot_confusion_matrix(h_opt, # trained optimal hypothesis model
X_test,
y_test,
)
plt.xticks(rotation=45)
plt.show()
Die Verwirrungsmatrix eines exakten Modells hat nur diagonale Einträge größer als Null, während alle anderen Null sind. So zeigt die oben gezeigte Verwirrungsmatrix, dass unser SVM-Modell sehr gut bei der Vorhersage von Step-Pool- und Riffle-Pool-Morphologien funktioniert, aber aufgrund von nicht vielen Beobachtungen unzuverlässig Sandbett-Morphologien vorhersagt. Das Modell machte jedoch auch falsche Vorhersagen zu Step-Pool- und Riffle-Pool-Features. Zum Beispiel, gemäß der Verwirrungsmatrix, prognostizierte das Modell 6-mal Step-Pool, wo in Wirklichkeit (wahres Etikett), ebene Bett morphologische Einheiten vorherrschten, und es fälschlicherweise eine Flechtbeobachtung als Step-Pool-Beobachtung voraussagte. Die Sandbettvorhersagen sind unzuverlässig, da es nur 25 True-Label-Sandbettbeobachtungen gibt (im Gegensatz zu 66 Step-Pool-Beobachtungen). Daher sind die Sandbettbeobachtungen unausgewogen und eine Lösung zur Beseitigung der Unzuverlässigkeit könnte darin bestehen, mehr morphologische Sandbetteinheiten zu beproben (wie oben erläutert).
- Montgomery, D. R., & Buffington, J. (1997). Channel-reach morphology in mountain drainage basins. Geological Society of America Bulletin, 109(5), 596–611. https://doi.org/10.1130/0016-7606(1997)109<0596:CRMIMD>2.3.CO;2
- Recking, A., Piton, G., Vazquez-Tarrio, D., & Parker, G. (2016). Quantifying the morphological print of bedload transport. Earth Surface Processes and Landforms, 41(6), 809–822.
- Wyrick, J. R., & Pasternack, G. B. (2014). Geospatial organization of fluvial landforms in a gravel-cobble river: Beyond the riffle-pool couplet. Geomorphology, 213(Supplement C), 48–65. 10.1016/j.geomorph.2013.12.040
- Schwindt, S. (2017). Hydro-morphological processes through permeable sediment traps [Thesis No. 7655, Laboratory of Hydraulic Constructions (LCH), Ecole Polytechnique fédérale de Lausanne (EPFL)]. 10.5075/epfl-thesis-7655
- Franke, G. R. (2010). Multicollinearity. Wiley International Encyclopedia of Marketing.