Python 中的支持向量机使用 libsvm 特征示例
Support vector machine in Python using libsvm example of features
我搜集了很多像这样的 ebay 标题:
Apple iPhone 5 White 16GB Dual-Core
而且我已经用这种方式手动标记了所有这些
B M C S NA
其中 B=Brand (Apple) M=Model (iPhone 5) C=Color (White) S=Size (Size) NA=Not Assigned (Dual Core)
现在我需要使用 python 中的 libsvm 库训练 SVM classifier 以学习 ebay 标题中出现的序列模式。
我需要通过将问题视为 class化问题来提取该属性(品牌、型号、颜色、尺码)的新值。这样我就可以预测新模型了。
我想考虑这个功能:
* Position
- from the beginning of the title
- to the end of the listing
* Orthographic features
- current word contains a digit
- current word is capitalized
....
我不明白我怎么能把所有这些信息都提供给图书馆。官方文档缺少很多信息
我的 class 是品牌、型号、尺码、颜色、NA
SVM 算法的输入文件必须包含什么?
如何创建它?考虑到我在问题中作为示例的 4 个功能,我可以举一个该文件的示例吗?我还可以有一个我必须用来详细说明输入文件的代码示例吗?
* 更新 *
我想表示这些特征...我必须怎么做?
- 当前词的标识
我觉得我可以这样解读
0 --> Brand
1 --> Model
2 --> Color
3 --> Size
4 --> NA
如果我知道这个词是一个品牌,我会将该变量设置为 1 (true)。
在训练测试中这样做是可以的(因为我已经标记了所有的词)但是我怎么能为测试集做呢?我不知道一个词的类别是什么(这就是我学习它的原因:D)。
N-gram 当前词的子串特征(N=4,5,6)
不知道,这是什么意思?
当前单词前2个单词的标识。
我该如何建模此功能?
考虑到我为第一个特征创建的图例,我有 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 变量,当且仅当我在 4 个词典之一中匹配当前单词时,我才会将其设置为 true。
- 品牌名称词典的独家会员资格
我认为就像在 4. 功能中一样,我必须使用 bool 变量。你同意吗?
我赞同@MarcoPashkov 的评论,但会尝试详细说明 LibSVM 文件格式。我发现文档很全面但很难找到,对于 Python 库,我推荐 README on 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"
在Heart Scale Example中找到的格式是一种稀疏格式,其中字典键是特征索引,字典值是特征值,第一个值是类别。
稀疏格式在使用 Bag of Words Representation 作为特征向量时非常有用。
As most documents will typically use a very small subset of the words used in the corpus, the resulting matrix will have many feature values that are zeros (typically more than 99% of them).
For instance a collection of 10,000 short text documents (such as emails) will use a vocabulary with a size in the order of 100,000 unique words in total while each document will use 100 to 1000 unique words individually.
为了使用您开始使用的特征向量作为示例,我训练了一个基本的 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)
我希望这个例子对你有所帮助,它不应该用于你的训练。它仅作为示例,因为它效率低下。
这里有一个分步指南,介绍如何使用您的数据训练 SVM,然后使用相同的数据集进行评估。它也可以在 http://nbviewer.ipython.org/gist/anonymous/2cf3b993aab10bf26d5f. At the url you can also see the output of the intermediate data and the resulting accuracy (it's an iPython notebook)
第 0 步:安装依赖项
您需要安装以下库:
- pandas
- scikit-学习
从命令行:
pip install pandas
pip install scikit-learn
第 1 步:加载数据
我们将使用 pandas 来加载我们的数据。
pandas 是一个方便加载数据的库。为了说明,我们先保存
将数据采样到 csv,然后加载它。
我们将使用 train.csv
训练 SVM 并使用 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 步:处理数据
我们会将我们的数据框转换为 numpy 数组,这是一种 scikit-
学懂了。
我们需要将标签 "B"、"M"、"C"、... 转换为数字,因为 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#svm
- 一长串 scikit-learn 示例: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
替换为您的测试数据,并获得测试数据的预测以及准确性结果。
请注意,由于您是使用训练的数据进行评估,因此准确度会异常高。
我搜集了很多像这样的 ebay 标题:
Apple iPhone 5 White 16GB Dual-Core
而且我已经用这种方式手动标记了所有这些
B M C S NA
其中 B=Brand (Apple) M=Model (iPhone 5) C=Color (White) S=Size (Size) NA=Not Assigned (Dual Core)
现在我需要使用 python 中的 libsvm 库训练 SVM classifier 以学习 ebay 标题中出现的序列模式。
我需要通过将问题视为 class化问题来提取该属性(品牌、型号、颜色、尺码)的新值。这样我就可以预测新模型了。
我想考虑这个功能:
* Position
- from the beginning of the title
- to the end of the listing
* Orthographic features
- current word contains a digit
- current word is capitalized
....
我不明白我怎么能把所有这些信息都提供给图书馆。官方文档缺少很多信息
我的 class 是品牌、型号、尺码、颜色、NA
SVM 算法的输入文件必须包含什么?
如何创建它?考虑到我在问题中作为示例的 4 个功能,我可以举一个该文件的示例吗?我还可以有一个我必须用来详细说明输入文件的代码示例吗?
* 更新 * 我想表示这些特征...我必须怎么做?
- 当前词的标识
我觉得我可以这样解读
0 --> Brand
1 --> Model
2 --> Color
3 --> Size
4 --> NA
如果我知道这个词是一个品牌,我会将该变量设置为 1 (true)。 在训练测试中这样做是可以的(因为我已经标记了所有的词)但是我怎么能为测试集做呢?我不知道一个词的类别是什么(这就是我学习它的原因:D)。
N-gram 当前词的子串特征(N=4,5,6) 不知道,这是什么意思?
当前单词前2个单词的标识。 我该如何建模此功能?
考虑到我为第一个特征创建的图例,我有 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 变量,当且仅当我在 4 个词典之一中匹配当前单词时,我才会将其设置为 true。
- 品牌名称词典的独家会员资格
我认为就像在 4. 功能中一样,我必须使用 bool 变量。你同意吗?
我赞同@MarcoPashkov 的评论,但会尝试详细说明 LibSVM 文件格式。我发现文档很全面但很难找到,对于 Python 库,我推荐 README on 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"
在Heart Scale Example中找到的格式是一种稀疏格式,其中字典键是特征索引,字典值是特征值,第一个值是类别。
稀疏格式在使用 Bag of Words Representation 作为特征向量时非常有用。
As most documents will typically use a very small subset of the words used in the corpus, the resulting matrix will have many feature values that are zeros (typically more than 99% of them).
For instance a collection of 10,000 short text documents (such as emails) will use a vocabulary with a size in the order of 100,000 unique words in total while each document will use 100 to 1000 unique words individually.
为了使用您开始使用的特征向量作为示例,我训练了一个基本的 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)
我希望这个例子对你有所帮助,它不应该用于你的训练。它仅作为示例,因为它效率低下。
这里有一个分步指南,介绍如何使用您的数据训练 SVM,然后使用相同的数据集进行评估。它也可以在 http://nbviewer.ipython.org/gist/anonymous/2cf3b993aab10bf26d5f. At the url you can also see the output of the intermediate data and the resulting accuracy (it's an iPython notebook)
第 0 步:安装依赖项
您需要安装以下库:
- pandas
- scikit-学习
从命令行:
pip install pandas
pip install scikit-learn
第 1 步:加载数据
我们将使用 pandas 来加载我们的数据。 pandas 是一个方便加载数据的库。为了说明,我们先保存 将数据采样到 csv,然后加载它。
我们将使用 train.csv
训练 SVM 并使用 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 步:处理数据
我们会将我们的数据框转换为 numpy 数组,这是一种 scikit- 学懂了。
我们需要将标签 "B"、"M"、"C"、... 转换为数字,因为 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#svm
- 一长串 scikit-learn 示例: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
替换为您的测试数据,并获得测试数据的预测以及准确性结果。
请注意,由于您是使用训练的数据进行评估,因此准确度会异常高。