Python 2.7 如何在Python Scikit learn中存储与预矢量化X匹配的预测类?
我想用名字来预测性别。不仅仅是名字,还有名字特征,比如把“姓氏”提取为从名字派生的特征。我的代码的流程是这样的,将数据放入df>指定lr分类器和dv dictVectorizer>使用函数创建特征>执行dictVectorization>训练。我想做以下工作,但找不到如何做的任何资源 1) 我想将预测的类(0和1)添加回原始数据集或可以看到名称和预测的性别类的数据集。目前我的y_测试预测只对应于X_测试,X_测试是一个稀疏矩阵 2) 我如何保留经过训练的分类器,并使用它来预测具有一组名称的不同数据集的性别?我怎么能插入一个名字“Rick Grime”让分类器告诉我它预测的性别 我用nltk做过类似的事情,但在Scikit learn中找不到任何这样做的示例或参考 代码:Python 2.7 如何在Python Scikit learn中存储与预矢量化X匹配的预测类?,python-2.7,machine-learning,scikit-learn,classification,prediction,Python 2.7,Machine Learning,Scikit Learn,Classification,Prediction,我想用名字来预测性别。不仅仅是名字,还有名字特征,比如把“姓氏”提取为从名字派生的特征。我的代码的流程是这样的,将数据放入df>指定lr分类器和dv dictVectorizer>使用函数创建特征>执行dictVectorization>训练。我想做以下工作,但找不到如何做的任何资源 1) 我想将预测的类(0和1)添加回原始数据集或可以看到名称和预测的性别类的数据集。目前我的y_测试预测只对应于X_测试,X_测试是一个稀疏矩阵 2) 我如何保留经过训练的分类器,并使用它来预测具有一组名称的不同数
import pandas as pd
from pandas import DataFrame, Series
import numpy as np
import re
import random
import time
from random import randint
import csv
import sys
from sklearn.metrics import classification_report
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction import DictVectorizer
from sklearn.metrics import confusion_matrix as sk_confusion_matrix
from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt
from sklearn.metrics import precision_recall_curve
from sklearn import cross_validation
data = pd.read_csv("file.csv", header=0, encoding="utf-8")
df = DataFrame(data)
dv = DictVectorizer()
lr = LogisticRegression()
X = df.raw_name.values
X2 = df.name.values
y = df.gender.values
def feature_full_name(nameString):
try:
full_name = nameString
if len(full_name) > 1: # not accept name with only 1 character
return full_name
else: return '?'
except: return '?'
def feature_full_last_name(nameString):
try:
last_name = nameString.rsplit(None, 1)[-1]
if len(last_name) > 1: # not accept name with only 1 character
return last_name
else: return '?'
except: return '?'
def feature_name_entity(nameString2):
space = 0
try:
for i in nameString2:
if i == ' ':
space += 1
return space+1
except: return 0
my_dict = [{'last-name': feature_full_last_name(i)} for i in X]
my_dict2 = [{'name-entity': feature_name_entity(feature_full_name(i))} for i in X2]
all_dict = []
for i in range(0, len(my_dict)):
temp_dict = dict(
my_dict[i].items() + my_dict2[i].items()
)
all_dict.append(temp_dict)
newX = dv.fit_transform(all_dict)
X_train, X_test, y_train, y_test = cross_validation.train_test_split(newX, y, test_size=0.3)
lr.fit(X_train, y_train)
y_test_predictions = lr.predict(X_test)
我会使用scikit learn的一些内置工具来分割数据帧,对名称进行矢量化,并预测结果。然后,您可以将预测结果添加回测试数据帧。例如,使用一小组名称作为示例:
data = {'Bruce Lee': 'Male',
'Bruce Banner': 'Male',
'Bruce Springsteen': 'Male',
'Bruce Willis': 'Male',
'Sarah McLaughlin': 'Female',
'Sarah Silverman': 'Female',
'Sarah Palin': 'Female',
'Sarah Hyland': 'Female'}
import pandas as pd
df = pd.DataFrame.from_dict(data, orient='index').reset_index()
df.columns = ['name', 'gender']
print(df)
name gender
0 Sarah Silverman Female
1 Sarah Palin Female
2 Bruce Springsteen Male
3 Bruce Banner Male
4 Bruce Lee Male
5 Sarah Hyland Female
6 Sarah McLaughlin Female
7 Bruce Willis Male
现在我们可以使用scikit learn的CountVectorizer
来计算名称中的单词;这将产生与上面所做的基本相同的输出,只是它不会根据名称的长度等进行过滤。为了便于使用,我们将使用交叉验证的逻辑回归将其放入管道中:
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegressionCV
from sklearn.pipeline import make_pipeline
clf = make_pipeline(CountVectorizer(), LogisticRegressionCV(cv=2))
现在,我们可以将数据拆分为一个训练集/测试集,拟合管道,然后分配结果:
from sklearn.cross_validation import train_test_split
df_train, df_test = train_test_split(df, train_size=0.5, random_state=0)
clf.fit(df_train['name'], df_train['gender'])
df_test = df_test.copy() # so we can modify it
df_test['predicted'] = clf.predict(df_test['name'])
print(df_test)
name gender predicted
6 Sarah McLaughlin Female Female
2 Bruce Springsteen Male Male
1 Sarah Palin Female Female
7 Bruce Willis Male Male
类似地,我们可以将一个名称列表传递给管道并得到一个预测:
>>> clf.predict(['Bruce Campbell', 'Sarah Roemer'])
array(['Male', 'Female'], dtype=object)
如果您想在文本矢量化中实现更复杂的逻辑,您可以为输入数据创建一个自定义转换器:“scikit learn custom transformer”的web搜索应该会为您提供一组不错的示例
编辑:下面是一个使用自定义转换器从输入名称生成DICT的示例:
from sklearn.base import TransformerMixin
class ExtractNames(TransformerMixin):
def transform(self, X, *args):
return [{'first': name.split()[0],
'last': name.split()[-1]}
for name in X]
def fit(self, *args):
return self
trans = ExtractNames()
>>> trans.fit_transform(df['name'])
[{'first': 'Bruce', 'last': 'Springsteen'},
{'first': 'Bruce', 'last': 'Banner'},
{'first': 'Sarah', 'last': 'Hyland'},
{'first': 'Sarah', 'last': 'Silverman'},
{'first': 'Sarah', 'last': 'Palin'},
{'first': 'Bruce', 'last': 'Lee'},
{'first': 'Bruce', 'last': 'Willis'},
{'first': 'Sarah', 'last': 'McLaughlin'}]
现在,您可以使用DictVectorizer
将其放入管道中,以生成稀疏特征:
from sklearn.feature_extraction import DictVectorizer
from sklearn.pipeline import make_pipeline
pipe = make_pipeline(ExtractNames(), DictVectorizer())
>>> pipe.fit_transform(df['name'])
<8x10 sparse matrix of type '<class 'numpy.float64'>'
with 16 stored elements in Compressed Sparse Row format>
从这里,如果您愿意,您可以修改
ExtractNames
转换器来进行更复杂的特征提取(使用上面的一些代码),最终实现过程的管道实现,但只需在字符串输入列表上调用predict()
。希望有帮助 我会使用scikit learn的一些内置工具来分割数据帧、矢量化名称和预测结果。然后,您可以将预测结果添加回测试数据帧。例如,使用一小组名称作为示例:
data = {'Bruce Lee': 'Male',
'Bruce Banner': 'Male',
'Bruce Springsteen': 'Male',
'Bruce Willis': 'Male',
'Sarah McLaughlin': 'Female',
'Sarah Silverman': 'Female',
'Sarah Palin': 'Female',
'Sarah Hyland': 'Female'}
import pandas as pd
df = pd.DataFrame.from_dict(data, orient='index').reset_index()
df.columns = ['name', 'gender']
print(df)
name gender
0 Sarah Silverman Female
1 Sarah Palin Female
2 Bruce Springsteen Male
3 Bruce Banner Male
4 Bruce Lee Male
5 Sarah Hyland Female
6 Sarah McLaughlin Female
7 Bruce Willis Male
现在我们可以使用scikit learn的CountVectorizer
来计算名称中的单词;这将产生与上面所做的基本相同的输出,只是它不会根据名称的长度等进行过滤。为了便于使用,我们将使用交叉验证的逻辑回归将其放入管道中:
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.linear_model import LogisticRegressionCV
from sklearn.pipeline import make_pipeline
clf = make_pipeline(CountVectorizer(), LogisticRegressionCV(cv=2))
现在,我们可以将数据拆分为一个训练集/测试集,拟合管道,然后分配结果:
from sklearn.cross_validation import train_test_split
df_train, df_test = train_test_split(df, train_size=0.5, random_state=0)
clf.fit(df_train['name'], df_train['gender'])
df_test = df_test.copy() # so we can modify it
df_test['predicted'] = clf.predict(df_test['name'])
print(df_test)
name gender predicted
6 Sarah McLaughlin Female Female
2 Bruce Springsteen Male Male
1 Sarah Palin Female Female
7 Bruce Willis Male Male
类似地,我们可以将一个名称列表传递给管道并得到一个预测:
>>> clf.predict(['Bruce Campbell', 'Sarah Roemer'])
array(['Male', 'Female'], dtype=object)
如果您想在文本矢量化中实现更复杂的逻辑,您可以为输入数据创建一个自定义转换器:“scikit learn custom transformer”的web搜索应该会为您提供一组不错的示例
编辑:下面是一个使用自定义转换器从输入名称生成DICT的示例:
from sklearn.base import TransformerMixin
class ExtractNames(TransformerMixin):
def transform(self, X, *args):
return [{'first': name.split()[0],
'last': name.split()[-1]}
for name in X]
def fit(self, *args):
return self
trans = ExtractNames()
>>> trans.fit_transform(df['name'])
[{'first': 'Bruce', 'last': 'Springsteen'},
{'first': 'Bruce', 'last': 'Banner'},
{'first': 'Sarah', 'last': 'Hyland'},
{'first': 'Sarah', 'last': 'Silverman'},
{'first': 'Sarah', 'last': 'Palin'},
{'first': 'Bruce', 'last': 'Lee'},
{'first': 'Bruce', 'last': 'Willis'},
{'first': 'Sarah', 'last': 'McLaughlin'}]
现在,您可以使用DictVectorizer
将其放入管道中,以生成稀疏特征:
from sklearn.feature_extraction import DictVectorizer
from sklearn.pipeline import make_pipeline
pipe = make_pipeline(ExtractNames(), DictVectorizer())
>>> pipe.fit_transform(df['name'])
<8x10 sparse matrix of type '<class 'numpy.float64'>'
with 16 stored elements in Compressed Sparse Row format>
从这里,如果您愿意,您可以修改
ExtractNames
转换器来进行更复杂的特征提取(使用上面的一些代码),最终实现过程的管道实现,但只需在字符串输入列表上调用predict()
。希望有帮助 有没有一种方法可以将管道与DictVectorizer一起用于上面的示例?我有更多需要使用DictVectorizer的功能。是的,您可以将DictVectorizer
放入管道中,就像我在上面使用CountVectorizer
一样。您只需将dict列表传递到clf.fit()
。更好的做法是编写一个自定义转换器来接收字符串列表并创建dict,然后将其传递给DictVectorizer
。管道可以有任意多个步骤。对不起,请您在代码中显示“只需将dict列表传递给clf.fit()”,我在scikit学习方面不是很先进。或者让我知道一个我可以从中学习的参考将非常感谢。在上面,我定义了一个管道,第一步是使用CountVectorizer
,并将字符串列表传递给它。第一步,您可以使用DictVectorizer
定义一个管道,并向其传递一个dicts列表。我添加了一个编辑,并提供了一个示例,希望对您有所帮助。是否有一种方法可以将管道与DictVectorizer一起使用,以代替上面的示例?我有更多需要使用DictVectorizer的功能。是的,您可以将DictVectorizer
放入管道中,就像我在上面使用CountVectorizer
一样。您只需将dict列表传递到clf.fit()
。更好的做法是编写一个自定义转换器来接收字符串列表并创建dict,然后将其传递给DictVectorizer
。管道可以有任意多个步骤。对不起,请您在代码中显示“只需将dict列表传递给clf.fit()”,我在scikit学习方面不是很先进。或者让我知道我可以从中学习的参考资料将非常感谢。在上面,我定义了一个管道,第一个管道是CountVectorizer