我试图循环处理多个文本文档,并通过记录以下内容来创建特征集:
- 文本中的位置列表
- 关键短语的词性
- 每个关键短语的长度(其中的单词数量)
- 每个关键短语的频率
提取特征的代码片段:
# 获取关键词列表keyword_list = [line.split(':')[1].lower().strip() for line in keywords.splitlines() if ':' in line ]# 位置position_list = [ [m.start()/float(len(document)) for m in re.finditer(re.escape(kw),document,flags=re.IGNORECASE)] for kw in keyword_list] # 词性pos_list = []for key in keyword_list: pos_list.append([pos for w,pos in nltk.pos_tag(nltk.word_tokenize(key))]) # 每个关键词的长度len_list = [ len(k.split(' ')) for k in keyword_list] # 文本频率 freq_list = [ len(pos)/float(len(document)) for pos in position_list] target.extend(keyword_list) for i in range(0,len(keyword_list)): data.append([position_list[i],pos_list[i],len_list[i],freq_list[i]])
其中
- target : 关键词列表
- data : 特征列表
我将这些数据输入到分类器中:
from sklearn.cross_validation import train_test_splitX_train,X_test,y_train,y_test = train_test_split(data,target,test_size=0.25,random_state = 42)import numpy as npX_train = np.array(X_train)y_train = np.array(y_train)from sklearn import svmcls = svm.SVC(gamma=0.001,C=100) # 参数值很重要!cls.fit(X_train,y_train)predictions = cls.predict(X_test)
但是我得到了一个错误:
Traceback (most recent call last): File "supervised_3.py", line 113, in <module> cls.fit(X_train,y_train) File "/Library/Python/2.7/site-packages/sklearn/svm/base.py", line 150, in fit X = check_array(X, accept_sparse='csr', dtype=np.float64, order='C') File "/Library/Python/2.7/site-packages/sklearn/utils/validation.py", line 373, in check_array array = np.array(array, dtype=dtype, order=order, copy=copy)ValueError: setting an array element with a sequence
因此,我通过更改
data.append([position_list[i],pos_list[i],len_list[i],freq_list[i]])
为
data.append([len_list[i],freq_list[i]])
移除了所有列表项。这样它就工作了。
但我需要包含 position_list
和 pos_list
我认为它不工作是因为这两个是列表。所以,我尝试将它们转换为数组:
data.append([np.array(position_list[i]),np.array(pos_list[i]),len_list[i],freq_list[i]])
但我仍然得到相同的错误。
回答:
在特征提取代码的最后一个for循环中,你试图向 data
添加一个包含四个元素的列表,即 position_list[i]
, pos_list[i]
, len_list[i]
, freq_list[i]
。问题在于前两个元素本身就是列表,但单个特征必须是标量(这就是为什么将子列表转换为numpy数组不能解决问题的原因)。每个元素需要不同的解决方法:
position_list[i]
这是一个浮点数列表。你可以用从中计算的一些统计数据来替换这个列表,例如均值和标准差。pos_list[i]
这是从由nltk.pos_tag
生成的(标记,标签)形式的元组列表中提取的标签列表。标签(这些是字符串)可以通过计算它们的出现次数直接转换为数字。为了简单起见,我将仅添加'NN'
和'NNS'
标签的频率**。
要使你的代码工作,只需将最后一个for循环更改为:
for i in range(0, len(keyword_list)): positions_i = position_list[i] tags_i = pos_list[i] len_tags_i = float(len(tags_i)) m = np.mean(positions_i) s = np.std(positions_i) nn = tags_i.count('NN')/len_tags_i nns = tags_i.count('NNS')/len_tags_i data.append([m, s, nn, nns, len_list[i], freq_list[i]])
通过这样做,结果特征向量变为6维。不用说,你可以使用更高或更低数量的统计数据和/或标签频率,甚至可以使用不同的标签集。
* 在创建 pos_list
的for循环中使用的标识符 w,pos
有点误导。
** 你可以使用 collections.Counter
更有效地计算每个标签的出现次数。