Поддержка векторных машин в Python на примере функций libsvm
Я удалил много названий ebay, таких как этот:
Apple iPhone 5 White 16GB Dual-Core
и я вручную пометил их всех таким образом
B M C S NA
где B= бренд (Apple) M= модель (iPhone 5) C= цвет (белый) S= размер (размер) NA= не назначено (двухъядерный)
Теперь мне нужно обучить классификатор SVM, используя библиотеку libsvm в python, чтобы узнать шаблоны последовательностей, встречающиеся в заголовках ebay.
Мне нужно извлечь новое значение для этих атрибутов (марка, модель, цвет, размер), рассматривая проблему как классификационную. Таким образом, я могу предсказать новые модели.
Я хочу рассмотреть эту функцию:
* Position
- from the beginning of the title
- to the end of the listing
* Orthographic features
- current word contains a digit
- current word is capitalized
....
Я не могу понять, как я могу передать всю эту информацию в библиотеку. Официальный документ не хватает много информации
Мой класс - Марка, Модель, Размер, Цвет, NA
Что должен содержать входной файл алгоритма SVM?
как я могу создать это? Могу ли я иметь пример этого файла с учетом 4 функций, которые я привел в качестве примера в своем вопросе? Могу ли я также иметь пример кода, который я должен использовать для разработки входного файла?
* ОБНОВЛЕНИЕ * Я хочу представить эти функции... Как я могу это сделать?
- Идентичность текущего слова
Я думаю, что я могу интерпретировать это таким образом
0 --> Brand
1 --> Model
2 --> Color
3 --> Size
4 --> NA
Если я знаю, что это слово является торговой маркой, я установлю для этой переменной значение 1 (true). Это нормально делать в тренировочном тесте (потому что я пометил все слова), но как я могу сделать это для тестового набора? Я не знаю, какова категория слова (вот почему я изучаю это: D).
N-граммовые особенности подстроки текущего слова (N=4,5,6) Понятия не имею, что это значит?
Идентичность 2 слов перед текущим словом. Как я могу смоделировать эту функцию?
Учитывая легенду, которую я создаю для 1-го объекта, у меня есть комбинация 5^(5))
00 10 20 30 40
01 11 21 31 41
02 12 22 32 42
03 13 23 33 43
04 14 24 34 44
Как я могу преобразовать его в формат, понятный libsvm (или scikit-learn)?
- Членство в 4 словарях атрибутов
Опять же, как я могу это сделать? Имея 4 словаря (для цвета, размера, модели и марки), я считаю, что я должен создать переменную bool, для которой я установлю значение true, если и только если у меня есть совпадение текущего слова в одном из 4 словарей.
- Эксклюзивное членство в словаре торговых марок
Я думаю, что, как и в функции 4., я должен использовать переменную bool. Ты согласен?
2 ответа
Ниже приведено пошаговое руководство по обучению SVM с использованием ваших данных и последующей оценке с использованием того же набора данных. Он также доступен по адресу http://nbviewer.ipython.org/gist/anonymous/2cf3b993aab10bf26d5f. В URL вы также можете увидеть вывод промежуточных данных и полученную точность (это записная книжка iPython)
Шаг 0: Установите зависимости
Вам необходимо установить следующие библиотеки:
- панд
- scikit учиться
Из командной строки:
pip install pandas
pip install scikit-learn
Шаг 1: Загрузите данные
Мы будем использовать панд для загрузки наших данных. Pandas - это библиотека для простой загрузки данных. Для иллюстрации мы сначала сохраняем образцы данных в CSV, а затем загружаем их.
Мы будем тренировать SVM с train.csv
и получить тестовые метки с test.csv
import pandas as pd
train_data_contents = """
class_label,distance_from_beginning,distance_from_end,contains_digit,capitalized
B,1,10,1,0
M,10,1,0,1
C,2,3,0,1
S,23,2,0,0
N,12,0,0,1"""
with open('train.csv', 'w') as output:
output.write(train_data_contents)
train_dataframe = pd.read_csv('train.csv')
Шаг 2. Обработка данных
Мы преобразуем наш фрейм данных в массивные массивы, которые понимает Scikit-Learn.
Нам нужно преобразовать метки "B", "M", "C",... в числа также потому, что svm не понимает строки.
Тогда мы будем тренировать линейный SVM с данными
import numpy as np
train_labels = train_dataframe.class_label
labels = list(set(train_labels))
train_labels = np.array([labels.index(x) for x in train_labels])
train_features = train_dataframe.iloc[:,1:]
train_features = np.array(train_features)
print "train labels: "
print train_labels
print
print "train features:"
print train_features
Мы видим здесь, что длина train_labels
(5) точно соответствует количеству строк в trainfeatures
, Каждый элемент в train_labels
соответствует ряду.
Шаг 3: обучить SVM
from sklearn import svm
classifier = svm.SVC()
classifier.fit(train_features, train_labels)
Шаг 4: Оцените SVM по некоторым данным тестирования
test_data_contents = """
class_label,distance_from_beginning,distance_from_end,contains_digit,capitalized
B,1,10,1,0
M,10,1,0,1
C,2,3,0,1
S,23,2,0,0
N,12,0,0,1
"""
with open('test.csv', 'w') as output:
output.write(test_data_contents)
test_dataframe = pd.read_csv('test.csv')
test_labels = test_dataframe.class_label
labels = list(set(test_labels))
test_labels = np.array([labels.index(x) for x in test_labels])
test_features = test_dataframe.iloc[:,1:]
test_features = np.array(test_features)
results = classifier.predict(test_features)
num_correct = (results == test_labels).sum()
recall = num_correct / len(test_labels)
print "model accuracy (%): ", recall * 100, "%"
Ссылки и советы
- Пример кода для загрузки LinearSVC: http://scikitlearn.org/stable/modules/svm.html
- Длинный список примеров обучения scikit: http://scikitlearn.org/stable/auto_examples/index.html. Я нашел это слегка полезным, но часто смущал себя.
- Если вы обнаружите, что обучение SVM занимает много времени, попробуйте использовать LinearSVC: http://scikitlearn.org/stable/modules/generated/sklearn.svm.LinearSVC.html
- Вот еще одно руководство по ознакомлению с моделями машинного обучения: http://scikit-learn.org/stable/tutorial/basic/tutorial.html
Вы должны быть в состоянии взять этот код и заменить train.csv
с вашими данными обучения, test.csv
с вашими данными тестирования, и получить прогнозы для ваших тестовых данных, а также результаты точности.
Обратите внимание, что, поскольку вы оцениваете с использованием данных, которые вы обучили, точность будет необычно высокой.
Я повторяю комментарий @MarcoPashkov, но постараюсь уточнить формат файла LibSVM. Я нахожу документацию исчерпывающей, но трудно найти, для Python lib я рекомендую README на GitHub.
Важным моментом, который нужно признать, является то, что существует разреженный формат, в котором удаляются все объекты, которые равны 0, и плотный формат, в котором не удаляются объекты, которые равны 0. Эти два являются эквивалентными примерами каждого из README.
# Dense data
>>> y, x = [1,-1], [[1,0,1], [-1,0,-1]]
# Sparse data
>>> y, x = [1,-1], [{1:1, 3:1}, {1:-1,3:-1}]
y
Переменная хранит список всех категорий для данных.
x
переменная хранит вектор объекта.
assert len(y) == len(x), "Both lists should be the same length"
Формат, найденный в Примере шкалы сердца, является разреженным форматом, где ключ словаря - это индекс объекта, а значение словаря - это значение объекта, в то время как первое значение - это категория.
Разреженный формат невероятно полезен при использовании представления мешка слов для векторного элемента.
Поскольку в большинстве документов обычно используется очень небольшое подмножество слов, используемых в корпусе, результирующая матрица будет иметь множество значений функций, которые являются нулями (обычно более 99% из них).
Например, коллекция из 10000 коротких текстовых документов (например, электронных писем) будет использовать словарь размером порядка 100 000 уникальных слов, в то время как каждый документ будет использовать от 100 до 1000 уникальных слов по отдельности.
Для примера использования вектора характеристик, с которого вы начали, я обучил базовой модели LibSVM 3.20. Этот код не предназначен для использования, но может помочь показать, как создать и протестировать модель.
from collections import namedtuple
# Using namedtuples for descriptive purposes, in actual code a normal tuple would work fine.
Category = namedtuple("Category", ["index", "name"])
Feature = namedtuple("Feature", ["category_index", "distance_from_beginning", "distance_from_end", "contains_digit", "capitalized"])
# Separate up the set of categories, libsvm requires a numerical index so we associate each with an index.
categories = dict()
for index, name in enumerate("B M C S NA".split(' ')):
# LibSVM expects index to start at 1, not 0.
categories[name] = Category(index + 1, name)
categories
Out[0]: {'B': Category(index=1, name='B'),
'C': Category(index=3, name='C'),
'M': Category(index=2, name='M'),
'NA': Category(index=5, name='NA'),
'S': Category(index=4, name='S')}
# Faked set of CSV input for example purposes.
csv_input_lines = """category_index,distance_from_beginning,distance_from_end,contains_digit,capitalized
B,1,10,1,0
M,10,1,0,1
C,2,3,0,1
S,23,2,0,0
NA,12,0,0,1""".split("\n")
# We just ignore the header.
header = csv_input_lines[0]
# A list of Feature namedtuples, this will be trained as lists.
features = list()
for line in csv_input_lines[1:]:
split_values = line.split(',')
# Create a Feature with the values converted to integers.
features.append(Feature(categories[split_values[0]].index, *map(int, split_values[1:])))
features
Out[1]: [Feature(category_index=1, distance_from_beginning=1, distance_from_end=10, contains_digit=1, capitalized=0),
Feature(category_index=2, distance_from_beginning=10, distance_from_end=1, contains_digit=0, capitalized=1),
Feature(category_index=3, distance_from_beginning=2, distance_from_end=3, contains_digit=0, capitalized=1),
Feature(category_index=4, distance_from_beginning=23, distance_from_end=2, contains_digit=0, capitalized=0),
Feature(category_index=5, distance_from_beginning=12, distance_from_end=0, contains_digit=0, capitalized=1)]
# Y is the category index used in training for each Feature. Now it is an array (order important) of all the trained indexes.
y = map(lambda f: f.category_index, features)
# X is the feature vector, for this we convert all the named tuple's values except the category which is at index 0.
x = map(lambda f: list(f)[1:], features)
from svmutil import svm_parameter, svm_problem, svm_train, svm_predict
# Barebones defaults for SVM
param = svm_parameter()
# The (Y,X) parameters should be the train dataset.
prob = svm_problem(y, x)
model=svm_train(prob, param)
# For actual accuracy checking, the (Y,X) parameters should be the test dataset.
p_labels, p_acc, p_vals = svm_predict(y, x, model)
Out[3]: Accuracy = 100% (5/5) (classification)
Надеюсь, этот пример поможет, его не следует использовать для обучения. Это подразумевается в качестве примера только потому, что это неэффективно.