Четыре классификатора

машинное обучение

Класс искусственного интеллекта требует использования наивного алгоритма Байеса, алгоритма дерева решений, искусственной нейронной сети, алгоритма опорных векторов для классификации данных.

Загрузка данных и предварительная обработка данных

документ:

  • общие данные dataset.txt (вы можете самостоятельно разделить обучающий набор и тестовый набор)
  • Учебный набор test.csv
  • Predict.csv тестовый набор

содержание документа

Этикетка тип
buying low, med, high, vhigh
maint low, med, high, vhigh
doors 2, 3, 4, 5more
persons 2, 4, more
lugBoot small, med, big
safety low, med, high
classValue unacc, acc, good, vgood
import numpy as np


trans = {
    0: {'low': 0, 'med': 1, 'high': 2, 'vhigh': 3}, # buying
    1: {'low': 0, 'med': 1, 'high': 2, 'vhigh': 3}, # maint
    2: {'2': 0, '3': 1, '4': 2, '5more': 3},        # doors
    3: {'2': 0, '4': 1, 'more': 2},                 # persons
    4: {'small': 0, 'med': 1, 'big': 2},            # lugBoots
    5: {'low': 0, 'med': 1, 'high': 2},             # safety
    6: {'unacc': 0, 'acc': 1, 'good': 2, 'vgood': 3}  # classValue
}


def make_one_hot(data: list) -> np.array:
    return (np.arange(4)==data[:,None]).astype(np.integer)


def getData(filename: str, onehot: bool=False) -> list:
    """
    如果非one-hot编码,返回的形状为(x, 7);
    否则返回(x, 7, 4)
    """
    data = []
    with open(filename) as f:
        f.readline() # 读取第一行
        for line in f.readlines():
            tmp = line.strip().split(',')
            for i, t in enumerate(tmp):
                tmp[i] = trans[i][t]
            tmp = np.array(tmp)
            if onehot:
                tmp = make_one_hot(tmp)
            data.append(tmp)
    return np.array(data)

# 训练集
train_data = getData("test.csv")
train_data_1hot = getData("test.csv", True)

# 训练集参数&标签
train_paras, train_tags = train_data[:,:6], train_data[:,6]
# 训练集参数(one-hot),标签不需要one-hot
train_1hot_paras = train_data_1hot[:, :6, :]

# 测试集
test_data = getData("predict.csv")
test_data_1hot = getData("predict.csv", True)

# 测试集参数&标签
test_paras, test_tags = test_data[:, :6], test_data[:, 6]
# 测试集参数(one-hot),标签不需要one-hot
test_1hot_paras = test_data_1hot[:, :6, :]

# 给个样例
print("非one-hot参数")
print(test_paras[0])
print("非one-hot标签")
print(test_tags[0])

print("\none-hot参数")
print(test_1hot_paras[0])
非one-hot参数
[0 3 2 0 0 0]
非one-hot标签
0

one-hot参数
[[1 0 0 0]
 [0 0 0 1]
 [0 0 1 0]
 [1 0 0 0]
 [1 0 0 0]
 [1 0 0 0]]

Функция оценки

Теперь, когда вход определен, давайте определим единый метод оценки. Проще всего рассчитать его правильную норму. Он определяется как:

Accuracy = \frac{T}{T+F}

где T представляет количество правильно предсказанных выборок, а F представляет количество неверно предсказанных выборок.

Поскольку существует 4 типа предсказаний и типов исходных меток, можно получить 16 комбинаций, а множество T здесь содержит те комбинации, чьи предсказания и выходы равны. Можно отобразить эти 16 комбинаций.Чем больше значение на левой диагональной линии, тем лучше эффект классификации.

def predict_matrix(predicted, tags) -> np.ndarray:
    """ 返回预测矩阵 """
    mtx = np.zeros((4,4))  # 4*4矩阵
    for i, p in enumerate(predicted):
        mtx[p][tags[i]] += 1
    return mtx


def Accuracy(predict, tags, show_mtx=False) -> float:
    """ 返回准确率 """
    mtx = predict_matrix(predict, tags)
    if show_mtx:
        print(mtx)
    T = mtx[0][0] + mtx[1][1] + mtx[2][2] + mtx[3][3]
    return T / len(predict)

# 举个例子:
pred = np.random.randint(0, 4, 100)
tags = np.random.randint(0, 4, 100)

print("随机数:")
print("accuracy: %.4f" % Accuracy(pred, tags, True))
随机数:
[[ 6.  4.  3.  8.]
 [ 2.  3.  7. 10.]
 [ 3.  4.  4.  8.]
 [10.  7. 10. 11.]]
accuracy: 0.2400

1. Наивный Байес

1.1 Принцип

Наивный Байес — это просто формула

P(y|x_1,x_2,\dots,x_n) = \frac{P(y)P(x_1,x_2,\dots,x_n|y)}{P(x_1,x_2,\dots,x_n)}

Если добавить предположение о независимости, всеx_iотдельный

P(y|x_1,x_2,\dots,x_n) = \frac{P(y)\prod_{i=1}^{n}{P(x_i|y)}}{P(x_1,x_2,\dots,x_n)}

Так как для всех у,P(x_1,x_2,\dots,x_n)всегда одно и то же, поэтому его можно упростить до:

P(y|x_1,x_2,\dots,x_n) \propto P(y)\prod_{i=1}^{n}{P(x_i|y)}

Тогда для заданногоx_i,x_2,\dots,x_n, чтобы найти наиболее вероятное y, нужно перечислить все y, и пусть вероятность будет наибольшей:

\widehat{y} = \mathop{\arg\min}_{y}  P(y)\prod_{i=1}^{n}{Px_i|y}

1.2 Реализация

sklearn предоставляет множество наивных байесовских классификаторов: гауссовский наивный байесовский GaussianNB, полиномиальный наивный байесовский многочлен NB, наивный байесовский метод Бернулли BernoulliNB, комплементарный наивный байесовский комплементNB. Хотя разные байесовские классификаторы используют разные методы расчета весов, т.P(x|y)Предположения о распределении разные, но основные принципы схожи.

Здесь используется классификатор Gaussian Naive Bayes, основные параметры которого бывают двух типов:

  • priors : array-like, shape (n_classes,)

    Априорная вероятность каждого класса может быть не предоставлена. Если предоставлено, программа не выполняет автоматический расчет на основе ввода

  • var_smoothing : float, optional (default=1e-9)

    Доля максимальной дисперсии всех признаков, добавленная для расчета стабильности.

from sklearn.naive_bayes import GaussianNB 

NB_clf = GaussianNB()
NB_clf.fit(train_paras, train_tags)

# 朴素贝叶斯预测

# 准确率
acc_on_train = Accuracy(NB_clf.predict(train_paras), train_tags, True)
print("Accuracy of Naive Bayes working on training set is %.4f" % acc_on_train)

acc_on_test = Accuracy(NB_clf.predict(test_paras), test_tags, True)
print("Accuracy of Naive Bayes working on testing set is %.4f" % acc_on_test)
[[852. 109.   0.   0.]
 [ 41. 136.   0.   0.]
 [ 58.  10.  23.   2.]
 [ 39.  56.   0.  24.]]
Accuracy of Naive Bayes working on training set is 0.7667
[[217.  38.   9.   0.]
 [  3.  35.  37.  39.]
 [  0.   0.   0.   0.]
 [  0.   0.   0.   0.]]
Accuracy of Naive Bayes working on testing set is 0.6667

1.3 Поиск наилучшей комбинации параметров

Приведенные выше результаты не очень хороши. Следовательно, необходимо установить параметры, чтобы алгоритм наивного Байеса играл большую роль. Если вам нужны более точные приоритеты, то сначала нужно знать распределение вероятностей общей выборки, то есть знать всю информацию из "data.csv", но это потеряет смысл "обучения" и не сможет правильно отразить моделиОбобщение. Так что не расставляйте приоритеты.

Не очень понятен смысл еще одного параметра, не знаю, ограничивает ли он максимальную дисперсию? Однако, чтобы решить дискретное перечисление в определенном диапазоне, выберите var_smoothing, который максимизирует правильную скорость.

# Setting the var—smoothing
best_smooths = 0
accuracy_NB = 0

for smooth in np.linspace(1e-2, 1, 500):
    # Set and fit
    NB_clf.set_params(var_smoothing=smooth)
    NB_clf.fit(test_paras, test_tags)
    # Test
    pred = NB_clf.predict(test_paras)
    acc = Accuracy(pred, test_tags)
    if acc > accuracy_NB:
        accuracy_NB = acc
        best_smooths = smooth

print(
    "Var_smoothing = %f leads to best accuracy %.4f" % (
        best_smooths,
        accuracy_NB
    )
)
Var_smoothing = 0.053647 leads to best accuracy 0.8254

Кажется, что лучшее, чего вы можете достичь с помощью Gaussian Naive Bayes, — это 82,54% правильности, что не особенно хорошо. Давайте попробуем другие классификаторы дальше.

2. Дерево решений

2.1 Принцип

Дерево решений — это рекурсивно сгенерированное дерево с сильной способностью к обобщению.

Ключом к построению дерева решений является то, что для разделения каждого измерения каждое подразделение будет генерировать несколько подузлов с более высокой чистотой выборки, то есть категории выборок в подузлах будут максимально однородными.

2.1.1 Показатели классификации

Обычно используемым показателем для оценки «чистоты» некоторых образцов является информационная энтропия.

Entropy(X) = -\sum_{i=1}^{n}{p_ilogp_i}

и коэффициент Джини

Gini(X) = 1 - \sum_{i=1}^{n}{p_i^2}

вp_i- доля класса i в X. Характеристика этих двух показателей заключается в том, что при более однородной категории выборки значение, придаваемое показателем, меньше, а при полной принадлежности выборки к одной категории показатель равен 0.

С помощью меры «чистоты» выборки можно определить меру мощности атрибутивной классификации обучающих данных — прирост информации. Прирост информации от атрибута — это ожидаемое снижение энтропии из-за разделения выборок по этому атрибуту. Прирост информации атрибута A по отношению к выборке SGain(S,A)определяется как:

Gain(S,A) = Entropy(S) - \sum_{v \in V(A)}{\frac{|S_v|}{|S|}Entropy(S_v)}
  • V(A)диапазон значений атрибута A
  • S - выборочный набор
  • S_vэто набор выборок в S, где значение энтропии атрибута A равно v

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

2.1.2 Обрезка

Обрезка - это основной метод алгоритмов обучения дерева решений для борьбы с «переоснащением». При обучении дерева решений, чтобы как можно точнее классифицировать обучающие выборки, процесс разделения узлов повторяется, что иногда приводит к слишком большому количеству ветвей дерева решений.В это время обучающие выборки могут быть изучены настолько хорошо, что обучающая выборка сами образцы Некоторые особенности , которые являются общими свойствами всех данных, приводят к переоснащению. Следовательно, риск переобучения можно снизить, активно удаляя некоторые ветки.

2.2 Реализация

В деревьях решений для обучения и тестирования используются наборы данных и тестовые наборы, отличные от горячего кодирования.

Здесь используется класс DecisionTreeClassifier в sklearn, функция обученияfitКак правило, вам нужно только пройти набор тестов и метки.

DecisionTreeClassifier может принимать несколько параметров при создании экземпляра для настройки различных классификаторов. Критерий параметра выбирает функцию для оценки классификации, существует два вида коэффициента Джини Джини и информационная энтропия энтропии.

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

  • max_depth : int or None, optional (default=None)

    Этот параметр определяет максимальную глубину дерева решений.Если этот параметр не установлен, узел дерева решений будет классифицироваться до тех пор, пока выборки в узле не будут иметь одинаковую категорию или количество выборок не станет меньше, чем min_samples_split

  • min_samples_split : int, float, optional (default=2)

    Минимальное количество выборок, необходимое для разделения узла

  • min_samples_leaf : int, float, optional (default=1)

    Минимальное количество семплов, необходимое для того, чтобы стать узлом

  • min_weight_fraction_leaf : float, optional (default=0.)

    По крайней мере, сумма весов, необходимых для того, чтобы стать узлом (вес выборки узла учитывает вес всех выборок)

Придумать оптимальные параметры для вышеперечисленных параметров за один раз невозможно, это нужно пробовать медленно в сочетании с реальными результатами тренировок.

from sklearn import tree

tree_clf = tree.DecisionTreeClassifier(
    criterion="entropy",
    max_depth=10,
    min_samples_split=3,
    min_samples_leaf=2
)  # 实例化决策树分类器

tree_clf.fit(train_paras, train_tags)     # 这样就设置好了一个分类器

# 决策树预测

# 准确率
acc_on_train = Accuracy(tree_clf.predict(train_paras), train_tags, True)
print("Accuracy of Naive Bayes working on training set is %.4f" % acc_on_train)

acc_on_test = Accuracy(tree_clf.predict(test_paras), test_tags, True)
print("Accuracy of Naive Bayes working on testing set is %.4f" % acc_on_test)
[[990.   8.   1.   0.]
 [  0. 303.   1.   1.]
 [  0.   0.  21.   1.]
 [  0.   0.   0.  24.]]
Accuracy of Naive Bayes working on training set is 0.9911
[[220.  13.   2.   0.]
 [  0.  60.  23.  14.]
 [  0.   0.  21.   1.]
 [  0.   0.   0.  24.]]
Accuracy of Naive Bayes working on testing set is 0.8598

2.3 Поиск наилучшей комбинации параметров

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

criterion = ""
best_deep = 0
best_split = 0
best_leaf = 0
accuracy_tree = 0.0

for cri in ["entropy", "gini"]:
    for deep in range(15, 5, -1):
        for sp in range(2, 5):
            for leaf in range(1, sp):
                tree_clf.set_params(  # 设置参数
                    criterion = cri,
                    max_depth=deep,
                    min_samples_split=sp,
                    min_samples_leaf=leaf
                )
                tree_clf.fit(train_paras, train_tags) # 训练
            
                # 测试
                pred = tree_clf.predict(test_paras)
                acc = Accuracy(pred, test_tags)
                if acc >= accuracy_tree:
                    accuracy_tree = acc
                    criterion = cri
                    best_deep = deep
                    best_split = sp
                    best_leaf = leaf

print(
    "Best accuracy is %.4f when\ncriterion is %s\nmax_depth = %d\nmin_samples_split = %d\nmin_samples_leaf = %d" % (
        accuracy_tree,
        criterion,
        best_deep,
        best_split,
        best_leaf
    )
)
Best accuracy is 0.8783 when
criterion is gini
max_depth = 11
min_samples_split = 2
min_samples_leaf = 1

Окончательный результат классификации дерева решений лучше, чем наивный байесовский классификатор.

2.4 Визуальное дерево решений

Сторонняя библиотека graphviz, которую необходимо использовать. Способ установки:

conda install python-graphviz

Метод использования следующий, и, наконец, файл PDF будет создан в текущем каталоге.

import os

if os.name == 'posix':
    print("不支持")
else: 
    import graphviz
    
    tree_clf.set_params(
        criterion = criterion,
        max_depth=best_deep,
        min_samples_split=best_split,
        min_samples_leaf=best_leaf
    )
    dot_data = tree.export_graphviz(tree_clf, out_file=None)
    graph = graphviz.Source(dot_data)
    graph.render("House")
    print("生成成功")
生成成功

3. SVM

3.1 Принцип

Идея машины опорных векторов состоит в том, чтобы найти гиперплоскость в многомерном пространстве и максимизировать расстояние от ближайшей к гиперплоскости точки до гиперплоскости.

Данные обучающие выборки имеют вид:

D = \{(x_1,y_1),(x_2,y_2),\dots,(x_n,y_n)\}

Оптимальная гиперплоскость, найденная SVM, может быть описана следующим уравнением:

\vec{w}^{T}x + \vec{b} = 0

\vec{w}вектор представления,\vec{b}Указывает расстояние гиперплоскости от начала координат.

В общем, SVM выполняет задачу бинарной классификации, поэтомупутем масштабирования, расстояние между положительными образцами и гиперплоскостью может быть таким же, как и у отрицательных образцов, и оба равны 1, а положительные образцы распределены по гиперплоскости\vec{w}^T+\vec{b} \ge 1, отрицательные примеры находятся ниже гиперплоскости\vec{w}^T+\vec{b} \le -1. Положительный и отрицательный примеры, ближайшие к гиперплоскости, могут сделать это неравенство равным, и векторы, представленные этими примерами, называются«Опорные векторы».

гиперплоскость\vec{w}^T+\vec{b} = 1и гиперплоскость\vec{w}^T+\vec{b} = -1расстояние между\gamma, что делает SVM, так это делает это\gammaмаксимизировать.\gammaРасстояние хорошо рассчитано:

\gamma = \frac{2}{\|\vec{w}\|}

Это выражение показывает, что нахождение максимального расстояния суммирует только\vec{w}Связанный. удовлетворять потребности\vec{w}и\vec{b}Это работа SVM, а методом решения является метод Лагранжа.

Преимуществ у машин опорных векторов много:

  • Эффективен в многомерном пространстве;
  • Все еще действует, когда количество измерений больше, чем количество выборок;
  • Пока предоставляются разные функции суммирования, могут быть сгенерированы разные машины опорных векторов;

Что делает дерево решений, так это максимально разделяет все категории, но SVM не только разделяет эти точки, но и делает классификацию максимально отказоустойчивой, поэтомуОжидается, что эффект от SVM будет лучше, чем от дерева решений..

Но у него также есть некоторые недостатки: если количество признаков намного больше, чем количество выборок, его легко переобучить, и в настоящее время решающее значение имеет член регуляризации.

3.2 Реализация

Библиотека sklearn предоставляет множество SVM, включая SVC, NuSVC, LinearSVC и т. д. Однако существует множество параметров дерева решений, в том числе следующие:

  • ядро: строка, необязательная (по умолчанию = 'rbf')
    • Функции ядра SVM включают линейные, поли, rbf, сигмоидальные, предварительно вычисленные и т. д.
  • degree : int, optional (default=3)
    • Если вы выбираете функцию ядра типа poly, вы можете указать размерность пространства, которая по умолчанию равна 3; другим функциям суммы этот параметр не нужен.
  • гамма : с плавающей запятой, необязательно (по умолчанию = 'авто')
    • Этот параметр используется, когда в качестве функции ядра используется rbf, поли или сигмоид. У него есть два варианта: масштаб и авто.
  • coef0 : float, optional (default=0.0)
    • Независимые члены в функции ядра. Он работает только в «поли» и «сигмоид».
  • solution_function_shape : 'ovo', 'ovr', по умолчанию = 'ovr'
    • решающая функция. ovr означает один против остальных, ovo означает один против одного. Последний используется для мультиклассификации.
  • C : float, optional (default=1.0)
    • Штраф за неверные условия
  • class_weight : {dict, 'сбалансированный'}, необязательный
    • По умолчанию все размеры одинаково важны. Разным измерениям можно присвоить разные веса.

Давайте сначала попробуем эффект от произвольно заданных параметров:

from sklearn import svm

SVM_clf = svm.SVC(
    gamma='auto',
    decision_function_shape='ovr'
)
SVM_clf.fit(train_paras, train_tags)

# SVM预测

# 准确率
acc_on_train = Accuracy(SVM_clf.predict(train_paras), train_tags, True)
print("Accuracy of SVM working on training set is %.4f" % acc_on_train)

acc_on_test = Accuracy(SVM_clf.predict(test_paras), test_tags, True)
print("Accuracy of SVM working on testing set is %.4f" % acc_on_test)
[[975.   8.   0.   0.]
 [ 15. 303.   4.   2.]
 [  0.   0.  19.   0.]
 [  0.   0.   0.  24.]]
Accuracy of SVM working on training set is 0.9785
[[217.   8.   1.   0.]
 [  2.  62.  22.  13.]
 [  1.   3.  22.   0.]
 [  0.   0.   1.  26.]]
Accuracy of SVM working on testing set is 0.8651

Произвольно сконфигурированный SVM, описанный выше, добился хороших результатов.

3.3 Поиск наилучшей комбинации параметров

Используя функцию полигонального ядра poly, попробуйте наилучшее сочетание параметров. Параметр с большим пространством для изменений здесь представляет собой степень и визуализирует производительность обученной SVM на обучающем наборе и тестовом наборе.

import matplotlib.pyplot as plt

degrees = [i for i in range(1, 8)]
train_acc = []
test_acc = []

best_degree = 0
best_acc = 0
best_mtx = None

for degree in degrees:
    # 配置参数
    SVM_clf.set_params(
        kernel='poly',
        degree=degree,
        gamma='auto',
        decision_function_shape='ovo'
    )
    # 训练
    SVM_clf.fit(train_paras, train_tags)
    # 测试结果
    acc1 = Accuracy(SVM_clf.predict(train_paras), train_tags)
    acc2 = Accuracy(SVM_clf.predict(test_paras), test_tags)
    # print(acc1, acc2)
    train_acc.append(acc1)
    test_acc.append(acc2)
    if acc2 > best_acc:
        best_degree = degree
        best_acc = acc2

plt.plot(degrees, train_acc, 'c')
plt.plot(degrees, test_acc, 'r')
plt.show()
print("Best accuracy is %.4f when degree is %d." % (best_acc, best_degree))

Best accuracy is 0.8995 when degree is 2.

Точность SVM, сконфигурированного выше на тренировочном наборе (голубая линия) и тестовом наборе (красная линия), показана на рисунке, а окончательный показатель точности составляет 89,95%, что является лучшим среди первых нескольких.

4. Искусственная нейронная сеть

4.1 Определение модели

Искусственные нейронные сети использовались много раз, и здесь мы используем инфраструктуру PyTorch для реализации полностью связанной нейронной сети. И этот набор данных относительно прост, каждый образец имеет только 6 измерений, поэтому нет необходимости определять слишком много скрытых слоев, но вы можете попробовать использовать линейные и нелинейные функции активации.

import torch
from torch import nn
import torch.optim as optim
from torch.autograd import Variable

# 定义神经网络
# 三层全连接
class Net1(nn.Module):
    def __init__(self, in_dim, hidden1, hidden2, out_dim):
        super(Net1, self).__init__()
        self.layers = nn.Sequential(
            nn.Linear(in_dim, hidden1),
            nn.Linear(hidden1, hidden2),
            nn.Linear(hidden2, out_dim)
        )
    def forward(self, x):
        return self.layers(x)

# 三层全连接+ReLU激活
class Net2(nn.Module):
    def __init__(self, in_dim, hidden1, hidden2, out_dim):
        super(Net2, self).__init__()
        self.layers = nn.Sequential(
            nn.Linear(in_dim, hidden1),
            nn.ReLU(inplace=True),
            nn.Linear(hidden1, hidden2),
            nn.ReLU(inplace=True),
            nn.Linear(hidden2, out_dim)
        )
    def forward(self, x):
        return self.layers(x)

# 三层全连接+Sigmoid
class Net3(nn.Module):
    def __init__(self, in_dim, hidden1, hidden2, out_dim):
        super(Net3, self).__init__()
        self.layers = nn.Sequential(
            nn.Linear(in_dim, hidden1),
            nn.Sigmoid(),
            nn.Linear(hidden1, hidden2),
            nn.Sigmoid(),
            nn.Linear(hidden2, out_dim)
        )
    def forward(self, x):
        return self.layers(x)

Три структуры нейронной сети определены выше:

  • Net1: трехслойное линейное полное соединение
  • Net2: трехуровневое полное соединение + функция активации ReLU
  • Net3: Трехуровневое полное соединение + функция активации Sigmoid

Однако эти сети все еще находятся на стадии определения и еще не созданы, поэтому при создании экземпляров необходимо учитывать тип и форму входных данных. Тип и форма входных данных следующие:

paras: 6 * 4
[[1 0 0 0]
 [0 0 0 1]
 [0 0 1 0]
 [1 0 0 0]
 [1 0 0 0]
 [1 0 0 0]]
tags: 1 * 4
[1 0 0 0]

Поскольку каждый нейрон может вводить числовое значение, нам сначала нужно6*4Тензор сглажен до1*24, поэтому для входного слоя требуется 24 нейрона, чтоin_dim=24. Тот же вывод содержит четыре измерения, поэтомуout_dim=4. Выходные данные среднего слоя не очень специфичны, но он не может содержать слишком много нейронов — это мешает нейронам изучить все входные данные и вызывает переоснащение.

4.2 Обучение модели

Затем следующий шаг — начать обучение.Входные и выходные данные сначала преобразуются в тип Variable, который может сохранять градиенты. При обучении введите train_1hot_paras, сравните результаты вывода сети с train_1hot_tags, и полученная ошибка будет распространяться обратно.Повторение таких шагов несколько раз может повысить точность.

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

Поскольку используется горячее кодирование, функция потерь CrossEntropy используется в следующем виде:

\text{loss}(x, class) = -\log\left(\frac{\exp(x[class])}{\sum_j \exp(x[j])}\right) = -x[class] + \log\left(\sum_j \exp(x[j])\right)

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

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

def Train_Test(net, epoch:int, batch_size:int, lr:float):
    epochs = [i for i in range(epoch)]
    train_acc, test_acc = [], []
    best_acc = 0
    
    criterion = nn.CrossEntropyLoss()  # Loss function
    optimizer = optim.Adam(net.parameters(), lr=lr)
    
    for epoch in epochs:
        # 训练
        for i in range(0, len(train_1hot_paras), batch_size):
            optimizer.zero_grad()
            inputs = Variable(torch.FloatTensor(train_1hot_paras[i: i+batch_size])).view(-1, 24)
            targets = Variable(torch.LongTensor(train_tags[i: i+batch_size]))
            outputs = net(inputs)
            loss = criterion(outputs, targets)
            loss.backward()   # 梯度反传
            optimizer.step()  # 学习

        # 检验训练集
        inputs = Variable(torch.FloatTensor(train_1hot_paras)).view(-1, 24)
        outputs = net(inputs)
        predict = outputs.topk(1)[1].view(-1)
        acc = Accuracy(predict, train_tags)
        train_acc.append(acc)
        # 检验测试集
        inputs = Variable(torch.FloatTensor(test_1hot_paras)).view(-1, 24)
        outputs = net(inputs)  # 需要将输出的one-hot分类转化为普通的分类
        predict = outputs.topk(1)[1].view(-1)
        acc = Accuracy(predict, test_tags)
        test_acc.append(acc)
        best_acc = max(acc, best_acc)
    
    print("Best accuracy on testing set is %.4f" % best_acc)
    plt.plot(epochs, train_acc, 'c')
    plt.plot(epochs, test_acc, 'r')
    plt.show()

4.2.1 Обучение линейной модели

Линейные полносвязные сети используют меньшие эпохи и увеличивают количество узлов в скрытом слое.

net1 = Net1(in_dim=24, hidden1=8, hidden2=8, out_dim=4)
Train_Test(net1, epoch=200, batch_size=8, lr=1e-2)
Best accuracy on testing set is 0.9286

4.2.2 Обучение модели активации ReLU

Сеть, использующая активацию ReLU, устанавливает меньше узлов скрытого слоя и увеличивает размер пакета, чтобы избежать переобучения.

net2 = Net2(in_dim=24, hidden1=8, hidden2=6, out_dim=4)
Train_Test(net2, epoch=200, batch_size=16, lr=1e-2)
Best accuracy on testing set is 0.8942

4.2.3 Обучение сигмовидной модели активации

Сеть, использующая активацию Sigmoid, также устанавливает меньше узлов скрытого слоя и увеличивает размер пакета, чтобы избежать переобучения.

net3 = Net2(in_dim=24, hidden1=6, hidden2=5, out_dim=4)
Train_Test(net3, epoch=200, batch_size=16, lr=1e-2)
Best accuracy on testing set is 0.9153

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

Наконец, эффекты четырех вышеперечисленных методов классификации на обучающей выборке следующие:

Классификатор Точность
Наивный Байес 82.54%
Древо решений 87.83%
SVM 89.95%
Искусственные нейронные сети 89%-93%

Способы повышения производительности

На самом деле, во многих задачах классификации веса различных параметров различны, и если соответствующие веса этих параметров могут быть известны заранее, производительность будет значительно улучшена. Многие функции 4 использованных выше методов классификации предоставляют весовые параметры, но они не используются.

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

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

Другой возможный способ - использовать несколько классификаторов одновременно, когда разные классификаторы выводят результаты, объединяют предложения каждого классификатора, а затем выбирают соответствующий результат. На самом деле существует алгоритм классификации:случайный лесОсновная идея такова.