Для получения дополнительных обновлений, пожалуйста, подпишитесь на мой блог@naivedatascientist.co.in
Классической проблемой в области распознавания образов является распознавание рукописных цифр. Предположим, у вас есть изображения рукописных цифр в диапазоне от 0 до 9, написанные разными людьми в коробках определенного размера — аналогично формам заявлений в банках и университетах.
Цель состоит в том, чтобы разработать модель, которая может правильно идентифицировать цифра (от 0 до 9), записанная на изображении. Для этой задачи мы используем данные MNIST, которые представляют собой большую базу данных рукописных цифр. «Значения пикселей» каждой цифры (изображения) составляют функции, а фактическое число от 0 до 9 является меткой. Поскольку каждое изображение имеет размер 28 x 28 пикселей, а каждый пиксель образует функцию, имеется 784 функции.
Чтение и проверка данных.
Importing important libraries import pandas as pd import numpy as np from sklearn.svm import SVC from sklearn.model_selection import train_test_split from sklearn import metrics from sklearn.metrics import confusion_matrix from sklearn.model_selection import KFold from sklearn.model_selection import cross_val_score from sklearn import svm from sklearn.model_selection import GridSearchCV import matplotlib.pyplot as plt import seaborn as sns from sklearn.preprocessing import scale import gc
Чтение данных
digit=pd.read_csv("DIGIT_RECOGNITION_SVM\\train.csv") digit.head() digit.info() <class 'pandas.core.frame.DataFrame'> RangeIndex: 42000 entries, 0 to 41999 Columns: 785 entries, label to pixel783 dtypes: int64(785) digit.describe() digit.isnull().sum(axis=1).any() False digit.isnull().sum(axis=0).any() False
Как видно отсюда, пропущенного значения как такового нет.
График некоторых цифр.
plt.figure(figsize=(12,6)) plt.subplot(1,4,1) zero=digit.iloc[1,1:] zero=zero.values.reshape(28,28) plt.imshow(zero,cmap='gray') plt.subplot(1,4,2) one=digit.iloc[0,1:] one=one.values.reshape(28,28) plt.imshow(one,cmap='gray') plt.subplot(1,4,3) two = digit.iloc[16, 1:] two = two.values.reshape(28, 28) plt.imshow(two, cmap='gray') plt.subplot(1,4,4) three=digit.iloc[7,1:] three=three.values.reshape(28,28) plt.imshow(three,cmap='gray')
digit['label'].value_counts() 1 4684 7 4401 3 4351 9 4188 2 4177 6 4137 0 4132 4 4072 8 4063 5 3795 round(digit['label'].value_counts()/len(digit.index)*100,2) 1 11.15 7 10.48 3 10.36 9 9.97 2 9.95 6 9.85 0 9.84 4 9.70 8 9.67 5 9.04 The percentage of all the digits appearing in the data is almost 10% +- 1% ,so in all we have fairly balanced data,bcoz svm normally does'nt do good work on unbalanced data. Splitting into X and Y x=digit.drop('label',axis=1) y=digit['label'] x=scale(x) Splitting into train and test,where training set is 20 % data and test set is 90 % data. x_train,x_test,y_train,y_test=train_test_split(x,y,train_size=0.10, random_state=10) print('x_train : ',x_train.shape) print('x_test : ',x_test.shape) print('y_train : ',y_train.shape) print('y_test : ',y_test.shape) x_train : (4200, 784) x_test : (37800, 784) y_train : (4200,) y_test : (37800,)
Построение модели.
linear model model_linear = SVC(kernel='linear') model_linear.fit(x_train,y_train) predict y_pred=model_linear.predict(x_test) y_pred[:10] array([7, 3, 9, 8, 6, 9, 7, 7, 9, 6], dtype=int64) confusion matrix accuracy print("accuracy:", metrics.accuracy_score(y_true=y_test, y_pred=y_pred), "\n") cm print(metrics.confusion_matrix(y_true=y_test, y_pred=y_pred)) accuracy: 0.8999470899470899 Class wise accuracy class_wise_accuracy=metrics.classification_report(y_true=y_test,y_pred=y_pred) print(class_wise_accuracy) precision recall f1-score support 0 0.93 0.97 0.95 3716 1 0.93 0.98 0.95 4201 2 0.87 0.88 0.87 3767 3 0.88 0.88 0.88 3949 4 0.85 0.93 0.88 3624 5 0.87 0.86 0.87 3456 6 0.95 0.94 0.94 3692 7 0.92 0.89 0.91 3975 8 0.91 0.82 0.86 3672 9 0.89 0.84 0.86 3748 gc.collect() 22
Нелинейная модель
Nonlinear SVM non_linear_model=svm.SVC(kernel='rbf') non_linear_model.fit(x_train,y_train) SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, decision_function_shape='ovr', degree=3, gamma='auto_deprecated', kernel='rbf', max_iter=-1, probability=False, random_state=None, shrinking=True, tol=0.001, verbose=False) Predict prediction= non_linear_model.predict(x_test) Accuracy print(metrics.accuracy_score(y_true=y_test, y_pred=prediction)) 0.9201851851851852 Confusion matrix print(metrics.confusion_matrix(y_true=y_test,y_pred=prediction)) [[3587 0 40 5 6 10 39 3 24 2] [ 0 4111 25 21 9 5 9 4 12 5] [ 19 16 3543 32 48 4 20 22 54 9] [ 12 19 219 3465 8 74 9 36 81 26] [ 5 7 87 0 3392 10 18 13 5 87] [ 27 12 70 107 35 3063 69 6 37 30] [ 20 6 110 0 13 35 3492 0 16 0] [ 8 33 173 7 69 3 2 3551 6 123] [ 18 52 72 67 25 81 18 14 3279 46] [ 15 11 94 57 119 9 1 112 30 3300]] Class wise accuracy class_wise_accuracy=metrics.classification_report(y_true=y_test,y_pred=prediction) print(class_wise_accuracy) precision recall f1-score support 0 0.97 0.97 0.97 3716 1 0.96 0.98 0.97 4201 2 0.80 0.94 0.86 3767 3 0.92 0.88 0.90 3949 4 0.91 0.94 0.92 3624 5 0.93 0.89 0.91 3456 6 0.95 0.95 0.95 3692 7 0.94 0.89 0.92 3975 8 0.93 0.89 0.91 3672 9 0.91 0.88 0.89 3748 micro avg 0.92 0.92 0.92 37800 macro avg 0.92 0.92 0.92 37800 weighted avg 0.92 0.92 0.92 37800 There is a slight increase in accuracy when using rbf kernel,now using grid search cv to tune hyper parameters. creating a KFold object with 5 splits folds = KFold(n_splits = 5, shuffle = True, random_state = 10) specify range of hyperparameters Set the parameters by cross-validation hyper_params = [ {'gamma': [1e-2, 1e-3, 1e-4], 'C': [1, 10, 100]}] specify model model = SVC(kernel="rbf") set up GridSearchCV() model_cv = GridSearchCV(estimator = model, param_grid = hyper_params, scoring= 'accuracy', n_jobs=-1, cv = folds, verbose = 1, return_train_score=True) fit the model model_cv.fit(x_train, y_train) cv_results=pd.DataFrame(model_cv.cv_results_) cv_results Converting c into numeric type to plot on x axis cv_results['param_C']=cv_results['param_C'].astype('int') plt.figure(figsize=(15,7)) plt.subplot(1,3,1) gamma_01 = cv_results[cv_results['param_gamma']==0.01] plt.plot(gamma_01["param_C"], gamma_01["mean_test_score"]) plt.plot(gamma_01["param_C"], gamma_01["mean_train_score"]) plt.xlabel('C') plt.ylabel('Accuracy') plt.title("Gamma=0.01") plt.ylim([0.60, 1]) plt.legend(['test accuracy', 'train accuracy'], loc='lower left') plt.xscale('log') plt.subplot(1,3,2) gamma_001 = cv_results[cv_results['param_gamma']==0.001] plt.plot(gamma_001["param_C"], gamma_001["mean_test_score"]) plt.plot(gamma_001["param_C"], gamma_001["mean_train_score"]) plt.xlabel('C') plt.ylabel('Accuracy') plt.title("Gamma=0.001") plt.ylim([0.60, 1]) plt.legend(['test accuracy', 'train accuracy'], loc='lower left') plt.xscale('log') plt.subplot(1,3,3) gamma_0001 = cv_results[cv_results['param_gamma']==0.0001] plt.plot(gamma_0001["param_C"], gamma_0001["mean_test_score"]) plt.plot(gamma_0001["param_C"], gamma_0001["mean_train_score"]) plt.xlabel('C') plt.ylabel('Accuracy') plt.title("Gamma=0.0001") plt.ylim([0.60, 1]) plt.legend(['test accuracy', 'train accuracy'], loc='lower left') plt.xscale('log')
printing the optimal accuracy score and hyperparameters best_score = model_cv.best_score_ best_hyperparams = model_cv.best_params_ print("The best test score is {0} corresponding to hyperparameters {1}".format(best_score, best_hyperparams)) The best test score is 0.9209523809523809 corresponding to hyperparameters {'C': 10, 'gamma': 0.001}
Из приведенного выше графика мы можем сделать вывод: 1) При gammaa=0,01 модель достигает приблизительно 75% на тестовых данных, но полностью на данных поезда.
2) При gamma = 0,001, первоначально при c = 1 обе точности сопоставимы, но по мере увеличения c модель начинает переобучать по мере увеличения данных поезда, а данных испытаний нет.
3) При gamma=0,0001 точность модели составляет до c=10, но при большом значении c она имеет тенденцию к переоснащению. Таким образом, отсюда мы можем сделать вывод, что наилучшее сочетание — c==10 и gamma=0,001, где точность теста самая высокая (~92%)¶
Построение и оценка окончательной модели.
окончательная модель с оптимальными гиперпараметрами и проверка максимальной точности.
модель
модель = SVC (C = 10, гамма = 0,001, ядро = rbf)
model.fit(x_train, y_train)
y_pred = model.predict(x_test)
показатели
print(accuracy, metrics.accuracy_score(y_test, y_pred), \n)
print(metrics.confusion_matrix(y_test, y_pred), \n)
accuracy 0.9316402116402116 [[3617 0 35 2 4 6 35 4 9 4] [ 0 4113 26 21 9 3 8 6 8 7] [ 18 15 3551 31 42 7 20 28 50 5] [ 12 9 156 3578 9 72 6 28 56 23] [ 7 8 72 0 3415 10 17 16 2 77] [ 29 12 53 103 34 3105 62 5 36 17] [ 17 4 75 0 12 22 3554 0 8 0] [ 7 32 141 11 70 2 2 3629 8 73] [ 24 46 75 71 25 76 20 8 3300 27] [ 10 5 75 59 103 17 2 102 21 3354]]
Вывод
Точность для линейного ядра составляет 90%, а для нелинейного ядра — 93%, можно сказать, что проблема носит нелинейный характер.¶