【发布时间】:2018-09-11 00:33:55
【问题描述】:
我的特征向量中有整数类型的特征,NLTK 的 NaiveBayesClassifier 将其视为标称值。
上下文
我正在尝试使用 n-gram 构建语言分类器。例如,二元组“th”在英语中比法语更常见。
对于我训练集中的每个句子,我提取如下特征:bigram(th): 5 其中 5(示例)表示二元组“th”在句子中出现的次数。
当我尝试构建具有此类特征的分类器并检查信息量最大的特征时,我意识到分类器没有意识到这些特征是线性的。例如,它可能会将bigram(ea): 4 视为法语,将bigram(ea): 5 视为英语,并将bigram(ea): 6 视为法语。这是相当随意的,并不代表二元组在英语或法语中更常见的逻辑。这就是为什么我需要这样对待整数。
更多想法
当然,我可以用has(th): True 等功能替换这些功能。但是,我认为这是一个坏主意,因为带有 1 个 'th' 实例的法语句子和带有 5 个 'th' 实例的英语句子都将具有无法区分它们的 has(th): True 特征。
我也找到了this relevant link,但它没有为我提供答案。
特征提取器
我的特征提取器如下所示:
def get_ngrams(word, n):
ngrams_list = []
ngrams_list.append(list(ngrams(word, n, pad_left=True, pad_right=True, left_pad_symbol='_', right_pad_symbol='_')))
ngrams_flat_tuples = [ngram for ngram_list in ngrams_list for ngram in ngram_list]
format_string = ''
for i in range(0, n):
format_string += ('%s')
ngrams_list_flat = [format_string % ngram_tuple for ngram_tuple in ngrams_flat_tuples]
return ngrams_list_flat
# Feature extractor
def get_ngram_features(sentence_tokens):
features = {}
# Unigrams
for word in sentence_tokens:
ngrams = get_ngrams(word, 1)
for ngram in ngrams:
features[f'char({ngram})'] = features.get(f'char({ngram})', 0) + 1
# Bigrams
for word in sentence_tokens:
ngrams = get_ngrams(word, 2)
for ngram in ngrams:
features[f'bigram({ngram})'] = features.get(f'bigram({ngram})', 0) + 1
# Trigrams
for word in sentence_tokens:
ngrams = get_ngrams(word, 3)
for ngram in ngrams:
features[f'trigram({ngram})'] = features.get(f'trigram({ngram})', 0) + 1
# Quadrigrams
for word in sentence_tokens:
ngrams = get_ngrams(word, 4)
for ngram in ngrams:
features[f'quadrigram({ngram})'] = features.get(f'quadrigram({ngram})', 0) + 1
return features
特征提取示例
get_ngram_features(['test', 'sentence'])
返回:
{'char(c)': 1,
'char(e)': 4,
'char(n)': 2,
'char(s)': 2,
'char(t)': 3,
'bigram(_s)': 1,
'bigram(_t)': 1,
'bigram(ce)': 1,
'bigram(e_)': 1,
'bigram(en)': 2,
'bigram(es)': 1,
'bigram(nc)': 1,
'bigram(nt)': 1,
'bigram(se)': 1,
'bigram(st)': 1,
'bigram(t_)': 1,
'bigram(te)': 2,
'quadrigram(_sen)': 1,
'quadrigram(_tes)': 1,
'quadrigram(ence)': 1,
'quadrigram(ente)': 1,
'quadrigram(est_)': 1,
'quadrigram(nce_)': 1,
'quadrigram(nten)': 1,
'quadrigram(sent)': 1,
'quadrigram(tenc)': 1,
'quadrigram(test)': 1,
'trigram(_se)': 1,
'trigram(_te)': 1,
'trigram(ce_)': 1,
'trigram(enc)': 1,
'trigram(ent)': 1,
'trigram(est)': 1,
'trigram(nce)': 1,
'trigram(nte)': 1,
'trigram(sen)': 1,
'trigram(st_)': 1,
'trigram(ten)': 1,
'trigram(tes)': 1}
【问题讨论】:
-
您是否尝试通过将事件与阈值进行比较来将其转化为名义特征? (即 th=5)
-
@KonstantinosKokos 这并不理想,因为很难确定所有 n-gram 的最佳阈值
-
@KonstantinosKokos 你的名字听起来是希腊语。实际上,我正在研究的确切问题涉及希腊语。你可以看这里:github.com/hb20007/greek-dialect-classifier/blob/master/…
-
看起来很有趣。我不知道您对朴素贝叶斯有多大的困扰,但我很确定其他简单的学习算法(例如随机森林)会自行选择阈值。
-
除了/而不是在句子中为
bigram(xx): n的每个可能值 n 进行特征化,只需计算字符密度:2*二元组数 'xx' / 句子中的字符数。是的,随机森林会发现能够最大程度提高杂质指标的特征和阈值。
标签: python machine-learning nltk text-classification n-gram