Здравствуйте, сегодня я собираюсь провести многоклассовую классификацию с помощью Keras. Функция активации, которую я выбрал, — это функция Softmax. Поговорим о том, почему я выбрал его.

Решающее различие между использованием двоичного набора данных и работой с мультиклассовым набором данных заключается в замене функций активации, таких как Sigmoid. Сигмовидная функция дает нам вероятность от 0 до 1:

Но теперь мы вводим более 2 классов. Так что эта функция больше не является идеальным выбором. Вместо этого мы будем использовать функцию Softmax. Уравнение того же ниже:

Приведенное выше уравнение дает нам вероятность некоторого балла «m», когда в наборе данных присутствует «n» классов. Итак, в основном, что мы делаем, для каждой оценки «m» «e^m» делится на сумму экспоненты всех оценок. Это гарантирует, что относительная величина всех оценок сохраняется, а также гарантирует, что все вероятности в сумме равны единице, как это требуется. Обратите внимание, что оценка «m» является выходом нейронной сети, и эта оценка будет разной для каждого класса.

Итак, теперь мы знаем, «почему» мы используем функцию Softmax и каковы ее преимущества. Давайте поговорим о другом важном факторе, перекрестной энтропии. В двоичном наборе данных формула для перекрестной энтропии была ниже:

Здесь мы взяли Ln вероятности точек в «положительной» области, которая затем была добавлена ​​к Ln вероятности точек в «отрицательной» области. Это делается для каждой отдельной точки, а затем принимается к отрицательному значению, чтобы получить общую перекрестную энтропию. Почему отрицательный? Я оставлю это для вас, чтобы узнать это.

Для мультиклассового набора данных в нашем случае возьмем 3, представьте, что для каждой точки будет 3 выходных вероятности, которые даст наша функция Softmax. Но фактическая вероятность для фактической метки будет только 1. Например, есть 3 класса фруктов: A, B и C. Теперь мы вводим A в нашу модель обучения, и наша модель дает 3 выхода в вероятностях: вероятность ввода равна фактически A, вероятность ввода B или вероятность ввода C. Таким образом, мы выберем вероятность ввода фактически A и возьмем Ln (вероятность A). Точно так же мы возьмем Ln (вероятность B), когда вход B, и Ln (вероятность C), когда вход C. Затем мы сложим все три и возьмем отрицательное значение. Почему отрицательный? :)

Обратите внимание, что если данные уже One Hot Encoded и вы добавляете все вероятности из всех 3 классов, поведение будет таким же.

Хватит математики, давайте перейдем к коду:

импортировать numpy как np
импортировать keras
из sklearn импортировать наборы данных
импортировать matplotlib.pyplot как plt
из keras.models импортировать Sequential
из keras.layers импортировать Dense
из keras.optimizers импортировать Адама
из keras.utils.np_utils импортировать в_categorical

Из вышеизложенного мы импортируем наборы данных из sklearn. Я также импортировал модель Sequential для определения своей нейронной сети. Я импортировал слой «Dense», так как он используется для подключения к предыдущим слоям в сети с последующими слоями. Я также импортировал оптимизатор Adam. Функция to_categorical используется для One Hot Encoding.

n= 1000
center= [[0,0],[1,1],[1,-1]]
x,y= datasets.make_blobs(n_samples=n,centers=center, cluster_std =.4)

Я специально упомянул центры, но это совершенно необязательно. Значение по умолчанию — 3. Здесь я использую «make_blobs» для создания кластеров. Параметр cluster_std плотность/ширина кластеров.

Давайте построим наш набор данных:

plt.scatter(x[y==0,0], x[y==0,1])
plt.scatter(x[y==1,0], x[y==1,1 ])
plt.scatter(x[y==2,0], x[y==2,1])

ycat = to_categorical (y, 3)

Вышеупомянутая функция имеет 2 параметра, первый — это столбец, который необходимо закодировать в горячем режиме, второй — количество классов, которые у нас есть в нашем наборе данных.

model= Sequential()
model.add(Dense(activation='softmax', unit=3, input_shape= (2,) ))
model.compile(optimizer=Adam(.1), метрики =['accuracy'], loss='categorical_crossentropy')
hist= model.fit(x,ycat,verbose=1,batch_size=100, epochs=20)

Здесь я создал простую нейронную сеть с 1 входным и 1 выходным слоями. В model.add активация fn — это Softmax, единиц измерения — 3, так как нам нужно 3 выхода, входная форма — это хорошо, входная форма. Модель скомпилирована с использованием оптимизатора Adam, а функция потерь — categorical_crossentropy. Рассчитаем точность модели. Наконец, мы обучаем модель с помощью model.fit. Verbose =1 используется для отображения прогресса, размер пакета равен 100, а эпоха равна 20. Обратите внимание, что меньшее количество эпох приводит к недостаточному соответствию, тогда как большее количество эпох приводит к переоснащению.

def plot_multiclass_decision_boundary(x, y, model):
x_span = np.linspace(min(x[:,0]) — 1, max(x[:,0]) + 1)
y_span = np.linspace(min(x[:,1]) — 1, max(x[:,1]) + 1)
xx, yy = np.meshgrid(x_span, y_span)
grid = np.c_[xx.ravel(), yy.ravel()]
pred_func = model.predict_classes(grid)
z = pred_func.reshape(xx.shape)
plt.contourf( хх, уу, з)

Приведенный выше код используется для построения границ. Здесь мы используем функцию model.predict_classes, в которую мы загружаем всю сетку массива, а обученная модель затем проверяет все точки и возвращает массив прогнозов. Наконец, мы строим контурные графики наших прогнозируемых результатов, используя функцию контура, которая будет отображать отдельные зоны класса.

plot_multiclass_decision_boundary(x, ycat, model)
plt.scatter(x[y==0, 0], x[y==0, 1])
plt.scatter(x[y==1 , 0], x[y==1, 1])
plt.scatter(x[y==2, 0], x[y==2, 1])

И вывод должен выглядеть примерно так:

Для тех, кому интересна точность:

И я думаю, что это завершает мультиклассовую классификацию с использованием нейронной сети.