NLTK 标题分类器
NLTK title classifier
如果这已经是 questioned/answered,我深表歉意,但我找不到任何接近我的问题的答案。我对处理 Python 也有点菜鸟,很抱歉这么长 post.
我正在尝试构建一个 Python 脚本,该脚本基于 user-given Pubmed 查询(即“癌症”),检索包含 N 篇文章标题的文件,并评估它们与以下内容的相关性有问题的主题。
我已经成功构建了“pubmed 搜索和保存”部分,return 一个包含文章标题的 .txt 文件(每一行对应不同的文章标题),例如:
Feasibility of an ovarian cancer quality-of-life psychoeducational intervention.
A randomized trial to increase physical activity in breast cancer survivors.
有了这个文件,我的想法是将它用于分类器,并让它回答 .txt 文件中的标题是否与主题相关,对此我有一个标题的“黄金标准”知道是相关的(即,我想知道根据我的黄金标准查询的标题集的精确度和召回率)。例如:标题 1 有 X 次“neoplasm”一词和 N 次“study”一词,因此它被认为与“cancer”相关(Y/N)。
为此,我一直在使用 NLTK 来(尝试)对我的文本进行分类。我采用了两种不同的方法,但均未成功:
方法一
加载 .txt 文件,对其进行预处理(标记化,lower-casing,删除停用词),将文本转换为 NLTK 文本格式,找到 N most-common 个单词。所有这一切都没有问题。
f = open('SR_titles.txt')
raw = f.read()
tokens = word_tokenize(raw)
words = [w.lower() for w in tokens]
words = [w for w in words if not w in stopwords.words("english")]
text = nltk.Text(words)
fdist = FreqDist(text)
>>><FreqDist with 116 samples and 304 outcomes>
我也能在文中找到colocations/bigrams,这可能对以后很重要。
text.collocations()
>>>randomized controlled; breast cancer; controlled trial; physical
>>>activity; metastatic breast; prostate cancer; randomised study; early
>>>breast; cancer patients; feasibility study; psychosocial support;
>>>group psychosocial; group intervention; randomized trial
在NLTKs tutorial之后,我构建了一个特征提取器,这样分类器就会知道它应该关注数据的哪些方面。
def document_features(document):
document_words = set(document)
features = {}
for word in word_features:
features['contains({})'.format(word)] = (word in document_words)
return features
例如,这将是 return 这样的事情:
{'contains(series)': False, 'contains(disorders)': False,
'contains(group)': True, 'contains(neurodegeneration)': False,
'contains(human)': False, 'contains(breast)': True}
接下来是使用特征提取器来训练分类器来标记新文章标题,并且按照 NLTKs 示例,我尝试了这个:
featuresets = [(document_features(d), c) for (d,c) in text]
这给了我错误:
ValueError: too many values to unpack
快速搜索了一下,发现这与元组有关,但没有得到我该如何解决它(就像我说的,我在这方面有点菜鸟),除非通过创建分类语料库(我仍然想了解如何解决这个元组问题)。
因此,我尝试了方法 2,遵循 Jacob Perkings Text Processing with NLTK Cookbook:
从创建语料库和归属类别开始。这次我有 2 个不同的 .txt 文件,每个标题文章的主题一个。
reader = CategorizedPlaintextCorpusReader('.', r'.*\,
cat_map={'hd_titles.txt': ['HD'], 'SR_titles.txt': ['Cancer']})
使用“reader.raw()”我得到这样的结果:
u"A pilot investigation of a multidisciplinary quality of life intervention for men with biochemical recurrence of prostate cancer.\nA randomized controlled pilot feasibility study of the physical and psychological effects of an integrated support programme in breast cancer.\n"
语料库的类别似乎是正确的:
reader.categories()
>>>['Cancer', 'HD']
然后,我尝试构建一个文档列表,并用适当的类别标记:
documents = [(list(reader.words(fileid)), category)
for category in reader.categories()
for fileid in reader.fileids(category)]
return我是这样的:
[([u'A', u'pilot', u'investigation', u'of', u'a', u'multidisciplinary',
u'quality', u'of', u'life', u'intervention', u'for', u'men', u'with',
u'biochemical', u'recurrence', u'of', u'prostate', u'cancer', u'.'],
'Cancer'),
([u'Trends', u'in', u'the', u'incidence', u'of', u'dementia', u':',
u'design', u'and', u'methods', u'in', u'the', u'Alzheimer', u'Cohorts',
u'Consortium', u'.'], 'HD')]
下一步将创建一个带标签的特征集列表,为此我使用了下一个函数,它需要一个语料库和一个 feature_detector 函数(上面提到的 document_features)。然后它构建并 returns 一个形式为 {label: [featureset]} 的映射。
def label_feats_from_corpus(corp, feature_detector=document_features):
label_feats = collections.defaultdict(list)
for label in corp.categories():
for fileid in corp.fileids(categories=[label]):
feats = feature_detector(corp.words(fileids=[fileid]))
label_feats[label].append(feats)
return label_feats
lfeats = label_feats_from_corpus(reader)
>>>defaultdict(<type 'list'>, {'HD': [{'contains(series)': True,
'contains(disorders)': True, 'contains(neurodegeneration)': True,
'contains(anilinoquinazoline)': True}], 'Cancer': [{'contains(cancer)':
True, 'contains(of)': True, 'contains(group)': True, 'contains(After)':
True, 'contains(breast)': True}]})
(列表要大得多,所有内容都设置为 True)。
然后我想构造一个带标签的训练实例和测试实例的列表。
split_label_feats() 函数采用 returned 的映射
label_feats_from_corpus() 并拆分每个特征集列表
进入带标签的训练和测试实例。
def split_label_feats(lfeats, split=0.75):
train_feats = []
test_feats = []
for label, feats in lfeats.items():
cutoff = int(len(feats) * split)
train_feats.extend([(feat, label) for feat in feats[:cutoff]])
test_feats.extend([(feat, label) for feat in feats[cutoff:]])
return train_feats, test_feats
train_feats, test_feats = split_label_feats(lfeats, split=0.75)
len(train_feats)
>>>0
len(test_feats)
>>>2
print(test_feats)
>>>[({'contains(series)': True, 'contains(China)': True,
'contains(disorders)': True, 'contains(neurodegeneration)': True},
'HD'), ({'contains(cancer)': True, 'contains(of)': True,
'contains(group)': True, 'contains(After)': True, 'contains(breast)':
True}, 'Cancer')]
我想我应该得到更多带标签的训练实例和带标签的测试实例。
这让我来到了现在的位置。我搜索了 Whosebug、biostars 等,但找不到如何处理这两个问题,所以任何帮助将不胜感激。
TL;DR: 无法标记单个 .txt 文件以对文本进行分类,也无法获得正确标记的语料库(再次,对文本进行分类)。
如果您已经读到这里,也谢谢您。
在 featuresets = [(document_features(d), c) for (d,c) in text]
中,我不确定您应该从 text
中得到什么。 text
似乎是一个 nltk class ,它只是一个生成器的包装器。似乎每次迭代都会给你一个字符串,这就是为什么你在要求两个项目而只有一个可以给出时会收到错误的原因。
您在以下行收到错误消息:
featuresets = [(document_features(d), c) for (d,c) in text]
在这里,您应该将每个文档(即每个标题)转换为一个特征字典。但是为了训练结果,train()
方法需要特征字典和正确答案 ("label")。所以正常的工作流程是有一个 (document, label)
对的列表,您将其转换为 (features, label)
对。看起来你的变量 documents
具有正确的结构,所以如果你只是使用它而不是 text
,这应该可以正常工作:
featuresets = [(document_features(d), c) for (d,c) in documents]
在你前进的过程中,养成仔细检查数据并弄清楚它们将会(和应该)发生什么的习惯。如果 text
是一个标题列表,将每个标题解包成一对 (d, c)
是没有意义的。那应该为您指明了正确的方向。
如果这已经是 questioned/answered,我深表歉意,但我找不到任何接近我的问题的答案。我对处理 Python 也有点菜鸟,很抱歉这么长 post.
我正在尝试构建一个 Python 脚本,该脚本基于 user-given Pubmed 查询(即“癌症”),检索包含 N 篇文章标题的文件,并评估它们与以下内容的相关性有问题的主题。
我已经成功构建了“pubmed 搜索和保存”部分,return 一个包含文章标题的 .txt 文件(每一行对应不同的文章标题),例如:
Feasibility of an ovarian cancer quality-of-life psychoeducational intervention.
A randomized trial to increase physical activity in breast cancer survivors.
有了这个文件,我的想法是将它用于分类器,并让它回答 .txt 文件中的标题是否与主题相关,对此我有一个标题的“黄金标准”知道是相关的(即,我想知道根据我的黄金标准查询的标题集的精确度和召回率)。例如:标题 1 有 X 次“neoplasm”一词和 N 次“study”一词,因此它被认为与“cancer”相关(Y/N)。
为此,我一直在使用 NLTK 来(尝试)对我的文本进行分类。我采用了两种不同的方法,但均未成功:
方法一
加载 .txt 文件,对其进行预处理(标记化,lower-casing,删除停用词),将文本转换为 NLTK 文本格式,找到 N most-common 个单词。所有这一切都没有问题。
f = open('SR_titles.txt')
raw = f.read()
tokens = word_tokenize(raw)
words = [w.lower() for w in tokens]
words = [w for w in words if not w in stopwords.words("english")]
text = nltk.Text(words)
fdist = FreqDist(text)
>>><FreqDist with 116 samples and 304 outcomes>
我也能在文中找到colocations/bigrams,这可能对以后很重要。
text.collocations()
>>>randomized controlled; breast cancer; controlled trial; physical
>>>activity; metastatic breast; prostate cancer; randomised study; early
>>>breast; cancer patients; feasibility study; psychosocial support;
>>>group psychosocial; group intervention; randomized trial
在NLTKs tutorial之后,我构建了一个特征提取器,这样分类器就会知道它应该关注数据的哪些方面。
def document_features(document):
document_words = set(document)
features = {}
for word in word_features:
features['contains({})'.format(word)] = (word in document_words)
return features
例如,这将是 return 这样的事情:
{'contains(series)': False, 'contains(disorders)': False,
'contains(group)': True, 'contains(neurodegeneration)': False,
'contains(human)': False, 'contains(breast)': True}
接下来是使用特征提取器来训练分类器来标记新文章标题,并且按照 NLTKs 示例,我尝试了这个:
featuresets = [(document_features(d), c) for (d,c) in text]
这给了我错误:
ValueError: too many values to unpack
快速搜索了一下,发现这与元组有关,但没有得到我该如何解决它(就像我说的,我在这方面有点菜鸟),除非通过创建分类语料库(我仍然想了解如何解决这个元组问题)。
因此,我尝试了方法 2,遵循 Jacob Perkings Text Processing with NLTK Cookbook:
从创建语料库和归属类别开始。这次我有 2 个不同的 .txt 文件,每个标题文章的主题一个。
reader = CategorizedPlaintextCorpusReader('.', r'.*\,
cat_map={'hd_titles.txt': ['HD'], 'SR_titles.txt': ['Cancer']})
使用“reader.raw()”我得到这样的结果:
u"A pilot investigation of a multidisciplinary quality of life intervention for men with biochemical recurrence of prostate cancer.\nA randomized controlled pilot feasibility study of the physical and psychological effects of an integrated support programme in breast cancer.\n"
语料库的类别似乎是正确的:
reader.categories()
>>>['Cancer', 'HD']
然后,我尝试构建一个文档列表,并用适当的类别标记:
documents = [(list(reader.words(fileid)), category)
for category in reader.categories()
for fileid in reader.fileids(category)]
return我是这样的:
[([u'A', u'pilot', u'investigation', u'of', u'a', u'multidisciplinary',
u'quality', u'of', u'life', u'intervention', u'for', u'men', u'with',
u'biochemical', u'recurrence', u'of', u'prostate', u'cancer', u'.'],
'Cancer'),
([u'Trends', u'in', u'the', u'incidence', u'of', u'dementia', u':',
u'design', u'and', u'methods', u'in', u'the', u'Alzheimer', u'Cohorts',
u'Consortium', u'.'], 'HD')]
下一步将创建一个带标签的特征集列表,为此我使用了下一个函数,它需要一个语料库和一个 feature_detector 函数(上面提到的 document_features)。然后它构建并 returns 一个形式为 {label: [featureset]} 的映射。
def label_feats_from_corpus(corp, feature_detector=document_features):
label_feats = collections.defaultdict(list)
for label in corp.categories():
for fileid in corp.fileids(categories=[label]):
feats = feature_detector(corp.words(fileids=[fileid]))
label_feats[label].append(feats)
return label_feats
lfeats = label_feats_from_corpus(reader)
>>>defaultdict(<type 'list'>, {'HD': [{'contains(series)': True,
'contains(disorders)': True, 'contains(neurodegeneration)': True,
'contains(anilinoquinazoline)': True}], 'Cancer': [{'contains(cancer)':
True, 'contains(of)': True, 'contains(group)': True, 'contains(After)':
True, 'contains(breast)': True}]})
(列表要大得多,所有内容都设置为 True)。
然后我想构造一个带标签的训练实例和测试实例的列表。
split_label_feats() 函数采用 returned 的映射 label_feats_from_corpus() 并拆分每个特征集列表 进入带标签的训练和测试实例。
def split_label_feats(lfeats, split=0.75):
train_feats = []
test_feats = []
for label, feats in lfeats.items():
cutoff = int(len(feats) * split)
train_feats.extend([(feat, label) for feat in feats[:cutoff]])
test_feats.extend([(feat, label) for feat in feats[cutoff:]])
return train_feats, test_feats
train_feats, test_feats = split_label_feats(lfeats, split=0.75)
len(train_feats)
>>>0
len(test_feats)
>>>2
print(test_feats)
>>>[({'contains(series)': True, 'contains(China)': True,
'contains(disorders)': True, 'contains(neurodegeneration)': True},
'HD'), ({'contains(cancer)': True, 'contains(of)': True,
'contains(group)': True, 'contains(After)': True, 'contains(breast)':
True}, 'Cancer')]
我想我应该得到更多带标签的训练实例和带标签的测试实例。
这让我来到了现在的位置。我搜索了 Whosebug、biostars 等,但找不到如何处理这两个问题,所以任何帮助将不胜感激。
TL;DR: 无法标记单个 .txt 文件以对文本进行分类,也无法获得正确标记的语料库(再次,对文本进行分类)。
如果您已经读到这里,也谢谢您。
在 featuresets = [(document_features(d), c) for (d,c) in text]
中,我不确定您应该从 text
中得到什么。 text
似乎是一个 nltk class ,它只是一个生成器的包装器。似乎每次迭代都会给你一个字符串,这就是为什么你在要求两个项目而只有一个可以给出时会收到错误的原因。
您在以下行收到错误消息:
featuresets = [(document_features(d), c) for (d,c) in text]
在这里,您应该将每个文档(即每个标题)转换为一个特征字典。但是为了训练结果,train()
方法需要特征字典和正确答案 ("label")。所以正常的工作流程是有一个 (document, label)
对的列表,您将其转换为 (features, label)
对。看起来你的变量 documents
具有正确的结构,所以如果你只是使用它而不是 text
,这应该可以正常工作:
featuresets = [(document_features(d), c) for (d,c) in documents]
在你前进的过程中,养成仔细检查数据并弄清楚它们将会(和应该)发生什么的习惯。如果 text
是一个标题列表,将每个标题解包成一对 (d, c)
是没有意义的。那应该为您指明了正确的方向。