1

У меня есть 9164 точки, где 4303 помечены как класс, который я хочу предсказать, а 4861 обозначены как не тот класс. Они не дублируют очки.sklearn SVM выполняет ужасно плохо

После How to split into train, test and evaluation sets in sklearn?, и, так как мой dataset является кортеж из 3-х элементов (ID, вектор, этикетка), я делаю:

df = pd.DataFrame(dataset) 
train, validate, test = np.split(df.sample(frac=1), [int(.6*len(df)), int(.8*len(df))]) 

train_labels = construct_labels(train) 
train_data = construct_data(train) 

test_labels = construct_labels(test) 
test_data = construct_data(test) 

def predict_labels(test_data, classifier): 
    labels = [] 
    for test_d in test_data: 
     labels.append(classifier.predict([test_d])) 
    return np.array(labels) 

def construct_labels(df): 
    labels = [] 
    for index, row in df.iterrows(): 
     if row[2] == 'Trump': 
      labels.append('Atomium') 
     else: 
      labels.append('Not Trump') 
    return np.array(labels) 

def construct_data(df): 
    first_row = df.iloc[0] 
    data = np.array([first_row[1]]) 
    for index, row in df.iterrows(): 
     if first_row[0] != row[0]: 
      data = np.concatenate((data, np.array([row[1]])), axis=0) 
    return data 

, а затем:

>>> classifier = SVC(verbose=True) 
>>> classifier.fit(train_data, train_labels) 
[LibSVM].......*..* 
optimization finished, #iter = 9565 
obj = -2718.376533, rho = 0.132062 
nSV = 5497, nBSV = 2550 
Total nSV = 5497 
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0, 
    decision_function_shape=None, degree=3, gamma='auto', kernel='rbf', 
    max_iter=-1, probability=False, random_state=None, shrinking=True, 
    tol=0.001, verbose=True) 
>>> predicted_labels = predict_labels(test_data, classifier) 
>>> for p, t in zip(predicted_labels, test_labels): 
...  if p == t: 
...    correct = correct + 1 

и я получаю только правильно 943 этикетки из 1833 (= LEN (test_labels)) -> (943 * 100/1843 = 51,4%)


Я suspe cting Мне не хватает чего-то большого времени здесь, может быть, я должен установить классификатор parameter, чтобы сделать более утонченную работу или что-то еще?

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


Попытка:

Я пошел Ахед и уменьшилось количество отрицательные примеры до 4303 (то же число, что и положительные примеры). Это немного улучшило точность.


Edit после ответа:

>>> print(clf.best_estimator_) 
SVC(C=1000.0, cache_size=200, class_weight='balanced', coef0=0.0, 
    decision_function_shape=None, degree=3, gamma=0.0001, kernel='rbf', 
    max_iter=-1, probability=False, random_state=None, shrinking=True, 
    tol=0.001, verbose=False) 
>>> classifier = SVC(C=1000.0, cache_size=200, class_weight='balanced', coef0=0.0, 
... decision_function_shape=None, degree=3, gamma=0.0001, kernel='rbf', 
... max_iter=-1, probability=False, random_state=None, shrinking=True, 
... tol=0.001, verbose=False) 
>>> classifier.fit(train_data, train_labels) 
SVC(C=1000.0, cache_size=200, class_weight='balanced', coef0=0.0, 
    decision_function_shape=None, degree=3, gamma=0.0001, kernel='rbf', 
    max_iter=-1, probability=False, random_state=None, shrinking=True, 
    tol=0.001, verbose=False) 

Также я попытался clf.fit(train_data, train_labels), который выполняется так же.


Редактировать данные (данные не являются случайными):

>>> train_data[0] 
array([ 20.21062112, 27.924016 , 137.13815308, 130.97432804, 
     ... # there are 256 coordinates in total 
     67.76352596, 56.67798138, 104.89566517, 10.02616417]) 
>>> train_labels[0] 
'Not Trump' 
>>> train_labels[1] 
'Trump' 
+0

SVM нужна настройка параметров, что очень важно (особенно нелинейные ядра). Вы, кажется, не настраиваете их. Также очень важно стандартизировать ваши данные (среднее значение и дисперсия). Используйте scikit-learns * GridSearchCV *, чтобы автоматически настраивать их с помощью перекрестной проверки. – sascha

+0

@sascha Не могли бы вы предоставить примеры или что-то еще? Я действительно новичок здесь! И то, что вы говорите, звучит действительно правильно! – gsamaras

+0

Просто читайте scikit-learns [руководство пользователя] (http://scikit-learn.org/stable/modules/svm.html). Это очень элементарные шаги, и я озадачен тем, почему люди используют такую ​​теоретически сложную концепцию, как SVM, даже не читая об основных правилах использования. [Heres a GridSearch example] (http://scikit-learn.org/stable/auto_examples/svm/plot_rbf_parameters.html), который также показывает, насколько важна настройка параметров -> точность между ~ [0.2, 0.95] – sascha

ответ

5

Большинство оценок в scikit-узнать, такие как SVC инициируются с числом входных параметров, также известный как гипер параметров. В зависимости от ваших данных вам нужно будет выяснить, что следует передавать в качестве входных данных для оценки во время инициализации. Если вы посмотрите на документацию SVC в scikit-learn, вы увидите, что ее можно инициализировать с использованием нескольких разных входных параметров.

Для простоты рассмотрим ядро, которое может быть «rbf» или «linear» (среди нескольких других вариантов); и C, который является параметром штрафа, и вы хотите попробовать значения 0.01, 0.1, 1, 10, 100 для C. Это приведет к созданию 10 различных возможных моделей для создания и оценки.

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

К счастью, scikit learn имеет лучший способ создать различные модели, основанные на разных комбинациях значений для вашей гипермодели и выбрать лучший. Для этого вы используете GridSearchCV. GridSearchCV инициализируется с использованием двух вещей: экземпляра оценки и словаря гиперпараметров и требуемых значений для изучения. Затем он будет запускаться и создавать все возможные модели с учетом выбора гиперпараметров и находит лучший, поэтому вам не нужно писать какие-либо вложенные петли.Вот пример:

from sklearn.grid_search import GridSearchCV 
print("Fitting the classifier to the training set") 
param_grid = {'C': [0.01, 0.1, 1, 10, 100], 'kernel': ['rbf', 'linear']} 
clf = GridSearchCV(SVC(class_weight='balanced'), param_grid) 
clf = clf.fit(train_data, train_labels) 
print("Best estimator found by grid search:") 
print(clf.best_estimator_) 

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

Возможно, GridSearchCV может занять очень много времени, чтобы создать все эти модели, чтобы найти лучший. Более практический подход заключается в том, чтобы вместо этого использовать RandomizedSearchCV, что создает случайное множество подмножеств всех возможных моделей (с использованием гиперпараметров). Он должен работать намного быстрее, если у вас много гиперпараметров, и его лучшая модель обычно хороша.

+0

В ответе отсутствуют некоторые объяснения, но он должен помочь OP. Просто некоторые замечания: GridSearchCV не пытается использовать все возможные модели, но декартово-произведение (упорядоченные комбинации) параметров-кандидатов определяет здесь шахины. Также: C и gamma являются наиболее важными параметрами при использовании SVM + rbf-ядра, поэтому они настроены здесь (их больше). Другое замечание: концепция перекрестной проверки не зависит от SVM. Это то, о чем следует также прочитать (также есть много параметров/понятий). – sascha

+0

shashins, что вы там подходите? Разве вы не имели в виду 'clf.fit (train_data, train_labels)'? Я только что применил ответ и получил точность 49,8%, с моей попыткой, это совсем не лучше ..:/Любые другие мысли? Я также думаю, что могу сделать что-то глупое, проверьте мой обновленный вопрос, пожалуйста! :) – gsamaras

+0

Я добавил больше объяснений в свой ответ. Я надеюсь, что это помогает. – shahins

1

После замечаний Sascha и ответа shahins, я сделал это в конце концов:

df = pd.DataFrame(dataset) 
train, validate, test = np.split(df.sample(frac=1), [int(.6*len(df)), int(.8*len(df))]) 

train_labels = construct_labels(train) 
train_data = construct_data(train) 

test_labels = construct_labels(test) 
test_data = construct_data(test) 

from sklearn.preprocessing import StandardScaler 
scaler = StandardScaler() 
train_data = scaler.fit_transform(train_data) 

from sklearn.svm import SVC 
# Classifier found with shahins' answer 
classifier = SVC(C=10, cache_size=200, class_weight='balanced', coef0=0.0, 
    decision_function_shape=None, degree=3, gamma='auto', kernel='rbf', 
    max_iter=-1, probability=False, random_state=None, shrinking=True, 
    tol=0.001, verbose=False) 
classifier = classifier.fit(train_data, train_labels) 

test_data = scaler.fit_transform(test_data) 
predicted_labels = predict_labels(test_data, classifier) 

и получил:

>>> correct_labels = count_correct_labels(predicted_labels, test_labels) 
>>> print_stats(correct_labels, len(test_labels)) 
Correct labels = 1624 
Accuracy = 88.5979268958 

с этими методами:

def count_correct_labels(predicted_labels, test_labels): 
    correct = 0 
    for p, t in zip(predicted_labels, test_labels): 
     if p[0] == t: 
      correct = correct + 1 
    return correct 

def print_stats(correct_labels, len_test_labels): 
    print "Correct labels = " + str(correct_labels) 
    print "Accuracy = " + str((correct_labels * 100/float(len_test_labels))) 

Я способный оптимизировать больше с настройкой более высокого параметра!

Полезная ссылка: RBF SVM parameters


Примечание: Если я не превращайте test_data, точность 52,7%.

+0

Хорошая работа. Похоже, ты его работаешь. – shahins

+0

Спасибо @shahins, ваша помощь была драгоценна! Я также построил [матрицу замешательства] (http://stackoverflow.com/questions/19233771/sklearn-plot-confusion-matrix-with-labels). Надеюсь, мой ответ поможет немногому будущему пользователю, несмотря на его оценку * 0 *! :) – gsamaras

Смежные вопросы