Как правило, мы обычно придерживаемся этого соглашения:
- Для небольшого количества функций, перейдите с
Logistic Regression
.
- Для большого количества функций, но не для большого количества данных, используйте
SVM
.
- Для большого количества функций и большого количества данных используйте
Neural Network
.
Поскольку ваш набор данных составляет 10K, было бы лучше использовать Logistic Regression
, потому что SVM
будет длиться вечно!.
Тем не менее, поскольку ваш набор данных содержит много классов, существует вероятность дисбаланса классов в вашей реализации. Поэтому я попытался обойти эту проблему, используя StratifiedKFold вместо train_test_split
, что не гарантирует сбалансированные классы в разбиениях.
Более того, я использовал GridSearchCV с StratifiedKFold , чтобы выполнить перекрестную проверку для настройки параметров и опробовать все различные оптимизаторы !
Итак, полная реализация выглядит следующим образом:
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV, StratifiedKFold, StratifiedShuffleSplit
import numpy as np
def getDataset(path, x_attr, y_attr):
"""
Extract dataset from CSV file
:param path: location of csv file
:param x_attr: list of Features Names
:param y_attr: Y header name in CSV file
:return: tuple, (X, Y)
"""
df = pd.read_csv(path)
X = X = np.array(df[x_attr]).reshape(len(df), len(x_attr))
Y = np.array(df[y_attr])
return X, Y
def stratifiedSplit(X, Y):
sss = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=0)
train_index, test_index = next(sss.split(X, Y))
X_train, X_test = X[train_index], X[test_index]
Y_train, Y_test = Y[train_index], Y[test_index]
return X_train, X_test, Y_train, Y_test
def run(X_data, Y_data):
X_train, X_test, Y_train, Y_test = stratifiedSplit(X_data, Y_data)
param_grid = {'C': [0.01, 0.1, 1, 10, 100, 1000], 'penalty': ['l1', 'l2'],
'solver':['newton-cg', 'lbfgs', 'liblinear', 'sag', 'saga']}
model = LogisticRegression(random_state=0)
clf = GridSearchCV(model, param_grid, cv=StratifiedKFold(n_splits=10))
clf.fit(X_train, Y_train)
print(accuracy_score(Y_train, clf.best_estimator_.predict(X_train)))
print(accuracy_score(Y_test, clf.best_estimator_.predict(X_test)))
X_data, Y_data = getDataset("data - Sheet1.csv", ['distance'], 'orders')
run(X_data, Y_data)
Несмотря на все попытки со всеми различными алгоритмами, точность не превышает 36% !!.
Почему это?
Если вы хотите, чтобы человек узнал / классифицировал другого человека по цвету его футболки, вы не можете сказать: эй, если он красный, это означает, что он Джон, а если красный, то это Питер, а если красный, то это Эйслинг !! Он сказал бы: «В самом деле, в чем разница?».
И это именно то, что находится в вашем наборе данных!
Просто запустите print(len(np.unique(X_data)))
и print(len(np.unique(Y_data)))
, и вы обнаружите, что цифры такие странные, в двух словах:
Number of Cases: 10000 !!
Number of Classes: 118 !!
Number of Unique Inputs (i.e. Features): 66 !!
Все классы делятся чертовски много информации, которая делает впечатляющим даже с точностью до 36%!
Другими словами, у вас нет информативных функций, которые приводят к отсутствию уникальности каждой модели класса!
Что делать?
Я считаю, что вам не разрешено удалять некоторые классы, поэтому у вас есть только два решения:
Либо жить с этим очень действительным результатом.
Или добавить более информативную функцию (и).
Обновление
Если вы предоставили тот же набор данных, но с дополнительными функциями (т. Е. Полным набором функций), ситуация теперь другая.
Я рекомендую вам сделать следующее:
Предварительно обработайте ваш набор данных (т.е. подготовьте его, вменяя пропущенные значения или удаляя строки, содержащие пропущенные значения, и конвертируя даты в некоторые уникальные значения ( пример ) .. Т.д.).
Проверьте, какие функции наиболее важны для классов Orders
. Вы можете достичь этого с помощью Forests of Trees
для оценки важности функций. Здесь - полный и простой пример того, как это сделать в Scikit-Learn
.
Создайте новую версию набора данных, но на этот раз удерживайте Orders
в качестве ответа Y
, а найденные выше функции в качестве X
переменных.
Выполните ту же процедуру GrdiSearchCV
и StratifiedKFold
, которую я показал вам в приведенной выше реализации.
Подсказка
Как упомянуто Вивеком Кумаром в комментарии ниже, параметр stratify
был добавлен в Scikit-learn
обновлении функции train_test_split .
Он работает, передавая основанную на массиве основную истину, поэтому вам не нужен мой обходной путь в функции stratifiedSplit(X, Y)
выше.