Я применил подход машинного обучения алгоритмов KNN, чтобы классифицировать опухолевые клетки как доброкачественные или злокачественные в базе данных рака молочной железы (Висконсин).
K-классификация ближайших соседей
Алгоритм KNN работает на предположении, что подобные вещи существуют в непосредственной близости или предполагаются, что подобные вещи находятся ближе друг к другу. Это простой в реализации алгоритм, который хорошо работает как для задач, основанных на регрессии, так и для задач классификации.
Алгоритм KNN можно обобщить старой пословицей
Рыбы одного полета
Как показано на изображении выше, точки данных, которые похожи друг на друга, расположены ближе друг к другу. Алгоритм KNN основывается на том, что это предположение достаточно верно для того, чтобы алгоритм был полезен. KNN отражает идею сходства (иногда называемого расстоянием, близостью или близостью) с некоторыми математическими выражениями, которым мы, возможно, учились в детстве, — вычислением расстояния между точками на графике.
Реализация алгоритма проходит
- Загрузка данных
- Инициализация k выбранным вами числом соседей.
Подробное объяснение можно найти здесь.
Теперь давайте получим набор данных и загрузим библиотеки. Набор данных можно получить здесь.
Вы также можете получить те же наборы данных от Kaggle.
Загрузка библиотек…
import itertools import numpy as np import matplotlib.pyplot as plt from matplotlib.ticker import NullFormatter import pandas as pd import numpy as np import matplotlib.ticker as ticker import seaborn as sns from sklearn import preprocessing %matplotlib inline
Теперь читаем файлы,
df = pd.read_csv('C:/breast-cancer-wisconsin-data/data.csv') df.head()
Визуализация и анализ данных
Во-первых, мы проверяем размер набора данных, который у нас есть.
df['radius_mean'].value_counts() print(df.shape) >> (569, 33)
Теперь мы делаем часть анализа
Здесь мы выполняем двоичную классификацию, поскольку модель машинного обучения хорошо работает только с числовыми значениями.
def diagnosis_value(diagnosis): if diagnosis == 'M': return 1 else: return 0 df['diagnosis'] = df['diagnosis'].apply(diagnosis_value) df.drop(['Unnamed: 32','id'],axis=1)
Обратите внимание, что в приведенном выше коде мы удалили столбец «Безымянный», так как в нем было слишком много значений NaN с помощью метода .drop().
plt.hist(df['radius_mean'] >> (array([ 19., 79., 185., 129., 55., 50., 38., 7., 4., 3.]), array([ 6.981 , 9.0939, 11.2068, 13.3197, 15.4326, 17.5455, 19.6584, 21.7713, 23.8842, 25.9971, 28.11 ]), <a list of 10 Patch objects>)
Давайте определим наши наборы функций,
X = df[[ 'radius_mean', 'texture_mean', 'perimeter_mean', 'area_mean', 'smoothness_mean', 'compactness_mean', 'concavity_mean', 'concave points_mean', 'symmetry_mean', 'fractal_dimension_mean', 'radius_se', 'texture_se', 'area_se', 'smoothness_se', 'compactness_se', 'concavity_se', 'concave points_se', 'symmetry_se', 'fractal_dimension_se', 'radius_worst', 'texture_worst', 'perimeter_worst', 'area_worst', 'smoothness_worst', 'compactness_worst', 'concavity_worst', 'concave points_worst', 'symmetry_worst', 'fractal_dimension_worst']] .values #.astype(float) X[0:4] y= np.array(df['diagnosis'])
Нормализация данных
Стандартизация данных дает данные с нулевым средним значением и единичной дисперсией, что является хорошей практикой, особенно для таких алгоритмов, как KNN, который основан на расстоянии случаев:
Для этого мы импортируем StandardScaler из библиотеки sklearn и создаем экземпляр, а также подгоняем модель.
X = preprocessing.StandardScaler().fit(X).transform(X.astype(float)) X[0:5] >>array([[ 1.09706398e+00, -2.07333501e+00, 1.26993369e+00, 9.84374905e-01, 1.56846633e+00, 3.28351467e+00, 2.65287398e+00, 2.53247522e+00, 2.21751501e+00, 2.25574689e+00, 2.48973393e+00, -5.65265059e-01, 2.48757756e+00, -2.14001647e-01, 1.31686157e+00, 7.24026158e-01, 6.60819941e-01, 1.14875667e+00, 9.07083081e-01, 1.88668963e+00, -1.35929347e+00, 2.30360062e+00, 2.00123749e+00, 1.30768627e+00, 2.61666502e+00, 2.10952635e+00, 2.29607613e+00, 2.75062224e+00, 1.93701461e+00], [ 1.82982061e+00, -3.53632408e-01, 1.68595471e+00, 1.90870825e+00, -8.26962447e-01, -4.87071673e-01, -2.38458552e-02, 5.48144156e-01, 1.39236330e-03, -8.68652457e-01, 4.99254601e-01, -8.76243603e-01, 7.42401948e-01, -6.05350847e-01, -6.92926270e-01, -4.40780058e-01, 2.60162067e-01, -8.05450380e-01, -9.94437403e-02, 1.80592744e+00, -3.69203222e-01, 1.53512599e+00, 1.89048899e+00, -3.75611957e-01, -4.30444219e-01, -1.46748968e-01, 1.08708430e+00, -2.43889668e-01, 2.81189987e-01], [ 1.57988811e+00, 4.56186952e-01, 1.56650313e+00, 1.55888363e+00, 9.42210440e-01, 1.05292554e+00, 1.36347845e+00, 2.03723076e+00, 9.39684817e-01, -3.98007910e-01, 1.22867595e+00, -7.80083377e-01, 1.18133606e+00, -2.97005012e-01, 8.14973504e-01, 2.13076435e-01, 1.42482747e+00, 2.37035535e-01, 2.93559404e-01, 1.51187025e+00, -2.39743838e-02, 1.34747521e+00, 1.45628455e+00, 5.27407405e-01, 1.08293217e+00, 8.54973944e-01, 1.95500035e+00, 1.15225500e+00, 2.01391209e-01], [-7.68909287e-01, 2.53732112e-01, -5.92687167e-01, -7.64463792e-01, 3.28355348e+00, 3.40290899e+00, 1.91589718e+00, 1.45170736e+00, 2.86738293e+00, 4.91091929e+00, 3.26373441e-01, -1.10409044e-01, -2.88378148e-01, 6.89701660e-01, 2.74428041e+00, 8.19518384e-01, 1.11500701e+00, 4.73268037e+00, 2.04751088e+00, -2.81464464e-01, 1.33984094e-01, -2.49939304e-01, -5.50021228e-01, 3.39427470e+00, 3.89339743e+00, 1.98958826e+00, 2.17578601e+00, 6.04604135e+00, 4.93501034e+00], [ 1.75029663e+00, -1.15181643e+00, 1.77657315e+00, 1.82622928e+00, 2.80371830e-01, 5.39340452e-01, 1.37101143e+00, 1.42849277e+00, -9.56046689e-03, -5.62449981e-01, 1.27054278e+00, -7.90243702e-01, 1.19035676e+00, 1.48306716e+00, -4.85198799e-02, 8.28470780e-01, 1.14420474e+00, -3.61092272e-01, 4.99328134e-01, 1.29857524e+00, -1.46677038e+00, 1.33853946e+00, 1.22072425e+00, 2.20556166e-01, -3.13394511e-01, 6.13178758e-01, 7.29259257e-01, -8.68352984e-01, -3.97099619e-01]])
Обучение и тестирование данных
Для этого мы выполняем train, test split на нашей модели,
from sklearn.model_selection import train_test_split, cross_val_score X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2) print ('Train set:', X_train.shape, y_train.shape) print ('Test set:', X_test.shape, y_test.shape) >> Train set: (455, 29) (455,) Test set: (114, 29) (114,)
Классификация
Теперь мы используем алгоритм KNN из библиотеки sklearn.
from sklearn.neighbors import KNeighborsClassifier
Обучение алгоритма с k равным 4 и прогнозирование.
Мы создали экземпляр KNN для нашей модели с помощью KNeighborsClassifier(n_neighbors = k).
k = 4 #Train Model and Predict neigh = KNeighborsClassifier(n_neighbors = k).fit(X_train,y_train) print(neigh) #predicting part yhat = neigh.predict(X_test) yhat[0:5] >>KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski', metric_params=None, n_jobs=None, n_neighbors=4, p=2, weights='uniform') array(['B', 'B', 'B', 'B', 'M'], dtype=object)
Итак, как вы можете видеть, модель предсказала значения «B» и «M», которые представляют собой доброкачественные и злокачественные опухоли соответственно.
Теперь для приведенной выше модели давайте проведем оценку точности…
from sklearn import metrics print("Train set Accuracy: ", metrics.accuracy_score(y_train, neigh.predict(X_train))) print("Test set Accuracy: ", metrics.accuracy_score(y_test, yhat)) >>Train set Accuracy: 0.9714285714285714 Test set Accuracy: 0.9473684210526315
Таким образом, мы получили точность 94,7% на тестовых данных, что довольно много.
Теперь давайте повторим описанную выше процедуру, но на этот раз с k равным 6.
k=6 neigh1=KNeighborsClassifier(n_neighbors=k).fit(X_train,y_train) print(neigh1) #predicting yhat6=neigh1.predict(X_test) print('Train Accuracy is : ',metrics.accuracy_score(y_train, neigh1.predict(X_train))) print('test accuracy is : ', metrics.accuracy_score(y_test, yhat6)) >>KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski', metric_params=None, n_jobs=None, n_neighbors=6, p=2, weights='uniform') Train Accuracy is : 0.9714285714285714 test accuracy is : 0.9649122807017544
Оценка точности для k = 6 на данных тестирования больше, чем k = 4.
Теперь я включил оценку точности для всех значений k до 10.
Ks = 10 mean_acc = np.zeros((Ks-1)) std_acc = np.zeros((Ks-1)) for n in range(1,Ks): #Train Model and Predict neigh = KNeighborsClassifier(n_neighbors = n).fit(X_train,y_train) yhat=neigh.predict(X_test) mean_acc[n-1] = metrics.accuracy_score(y_test, yhat) std_acc[n-1]=np.std(yhat==y_test)/np.sqrt(yhat.shape[0]) mean_acc >>array([0.95614035, 0.94736842, 0.95614035, 0.94736842, 0.96491228, 0.96491228, 0.96491228, 0.96491228, 0.96491228])
Построение показателей точности для различных значений k
plt.plot(range(1,Ks),mean_acc,'g') plt.fill_between(range(1,Ks),mean_acc - 1 * std_acc,mean_acc + 1 * std_acc, alpha=0.10) plt.legend(('Accuracy ', '+/- 3xstd')) plt.ylabel('Accuracy ') plt.xlabel('Number of estimators (K)') plt.tight_layout() plt.show()
Теперь давайте проверим, для какого значения k модель выдаст более высокую оценку точности.
print( "The best accuracy was with", mean_acc.max(), "with k=", mean_acc.argmax()+1) >>The best accuracy was with 0.9649122807017544 with k= 5
Полные коды предоставлены из моего репозитория Github здесь.
использованная литература
- https://medium.com/analytics-vidhya/detecting-breast-cancer-using-machine-learning-ab23e719f7fa
- https://labs.cognitiveclass.ai/tools/jupyterlab/lab/tree/labs/edX/ML0101EN/ML0101EN-Clas-K-Nearest-neighbors-CustCat-py-v1.ipynb
- https://towardsdatascience.com/machine-learning-basics-with-the-k-nearest-neighbors-algorithm-6a6e71d01761.