Машина опорных векторов — это контролируемое обучение, которое находит гиперплоскость в N-мерном пространстве для четкой классификации точек данных. SVM использует функцию потери шарнира и регуляризацию L2.
- Загрузка библиотек —
import numpy as np import pandas as pd import matplotlib.pyplot as plt from sklearn import datasets from sklearn.svm import SVC %matplotlib inline plt.rcParams['figure.figsize'] = (10, 5)
2. Загрузка и предварительная обработка набора данных —
# Loading the Iris Dataset. iris = datasets.load_iris() # Concatenating the first 2 features and Target column. df = pd.concat([pd.DataFrame(iris.data[:,:2], columns=iris.feature_names[:2]), pd.DataFrame({'Target':iris.target})], axis=1) print("Dataset : \n", df.head()) # Splitting the feature and target columns X = df.drop('Target', axis=1).values y = df['Target'].values
3. Создание функции построения графика —
def make_meshgrid(x, y, h=.02, lims=None): """Create a mesh of points to plot in Parameters ---------- x: data to base x-axis meshgrid on y: data to base y-axis meshgrid on h: stepsize for meshgrid, optional Returns ------- xx, yy : ndarray """ if lims is None: x_min, x_max = x.min() - 1, x.max() + 1 y_min, y_max = y.min() - 1, y.max() + 1 else: x_min, x_max, y_min, y_max = lims xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h)) return xx, yy # https://jakevdp.github.io/PythonDataScienceHandbook/04.04-density-and-contour-plots.html def plot_contours(ax, clf, xx, yy, proba=False, **params): """Plot the decision boundaries for a classifier. Parameters ---------- ax: matplotlib axes object clf: a classifier xx: meshgrid ndarray yy: meshgrid ndarray params: dictionary of params to pass to contourf, optional """ # if proba==True then make a probability contour graph. if proba: # ravel() - flattens the array to 1D. # .c_[a, b] - Add in the second axis. Row remains same but column adds. https://stackoverflow.com/questions/10894323/what-does-the-c-underscore-expression-c-do-exactly Z = clf.predict_proba(np.c_[xx.flatten(), yy.flatten()])[:,-1] Z = Z.reshape(xx.shape) out = ax.imshow(Z,extent=(np.min(xx), np.max(xx), np.min(yy), np.max(yy)), origin='lower', vmin=0, vmax=1, **params) ax.contour(xx, yy, Z, levels=[0.5]) # if proba==False then make a normal contour graph else: Z = clf.predict(np.c_[xx.flatten(), yy.flatten()]) Z = Z.reshape(xx.shape) out = ax.contourf(xx, yy, Z, **params) return out # Will only work for 2 columns in X and 1 in Y, proba can be set to True or False def plot_classifier(X, y, clf, xlab, ylab, title, ax=None, ticks=False, proba=False, lims=None): # assumes classifier "clf" is already fit # get all the values in first and second columns in X0 and X1. X0, X1 = X[:, 0], X[:, 1] # makes a meshgrid from min-1 to max+1 with intervals of 0.2 xx, yy = make_meshgrid(X0, X1, lims=lims) # if axis is None then make axes. if ax is None: plt.figure() ax = plt.gca() show = True else: show = False # can abstract some of this into a higher-level function for learners to call cs = plot_contours(ax, clf, xx, yy, cmap=plt.cm.coolwarm, alpha=0.8, proba=proba) if proba: cbar = plt.colorbar(cs) cbar.ax.set_ylabel('probability of red $\Delta$ class', fontsize=20, rotation=270, labelpad=30) cbar.ax.tick_params(labelsize=14) #ax.scatter(X0, X1, c=y, cmap=plt.cm.coolwarm, s=30, edgecolors=\'k\', linewidth=1) labels = np.unique(y) if len(labels) == 2: ax.scatter(X0[y==labels[0]], X1[y==labels[0]], cmap=plt.cm.coolwarm, s=60, c='b', marker='o', edgecolors='k') ax.scatter(X0[y==labels[1]], X1[y==labels[1]], cmap=plt.cm.coolwarm, s=60, c='r', marker='^', edgecolors='k') else: ax.scatter(X0, X1, c=y, cmap=plt.cm.coolwarm, s=50, edgecolors='k', linewidth=1) ax.set_xlim(xx.min(), xx.max()) ax.set_ylim(yy.min(), yy.max()) # ax.set_xlabel(data.feature_names[0]) # ax.set_ylabel(data.feature_names[1]) if ticks: ax.set_xticks(()) ax.set_yticks(()) # ax.set_title(title) if show: plt.xlabel(xlab) plt.ylabel(ylab) plt.title(title) plt.show() else: return ax
4. Линейный классификатор SVM —
# Linear SVM Classifier svm = SVC(kernel='linear') svm.fit(X, y) plot_classifier(X, y, svm, "Sepal Length (cm)", "Sepal Width (cm)", "Iris Dataset")
5. Построение опорных векторов линейного классификатора SVM —
# Subsetting the support vectors. X_small = X[svm.support_] y_small = y[svm.support_] # Linear SVM Classifier fitted with the support vectors. svm_n1 = SVC(kernel='linear') svm_n1.fit(X_small, y_small) plot_classifier(X_small, y_small, svm_n1, "Sepal Length (cm)", "Sepal Width (cm)", "Iris Dataset")
6. Классификатор SVM —
# Normal SVM Classifier svc = SVC() svc.fit(X, y) plot_classifier(X, y, svc, "Sepal Length (cm)", "Sepal Width (cm)", "Iris Dataset")
7. Построение опорного вектора классификатора SVM —
# Subsetting the support vectors. X_small = X[svc.support_] y_small = y[svc.support_] # SVM Classifier fitted with the support vectors. svc_n1 = SVC() svc_n1.fit(X_small, y_small) plot_classifier(X_small, y_small, svc_n1, "Sepal Length (cm)", "Sepal Width (cm)", "Iris Dataset")
Как мы видим на приведенных выше графиках, потеря шарнира учитывает только ошибочно предсказанные значения и точки вблизи границы решения. Все остальные точки данных игнорируются и не учитывают классификацию модели.
Я ценю вас и время, которое вы потратили на чтение этого дня!