机器学习/自然语言处理与关键词搜索,将非结构化数据转化为结构化数据的比较

3

我负责一个研究项目,其中我们汇总非洲政治暴力的报纸文章,然后识别和编码事件。我们跟踪事件发生的地点和时间、涉及的行动者、死亡人数等信息。您可以在这里查看数据集:

https://docs.google.com/spreadsheets/d/1_QYl4xhMu5nZVluprOgRs6rUzgkkBemapdsg5lFzKU/pubhtml

这是一个劳动密集型的过程,我认为机器学习可能会有所帮助。我正在尝试找出最佳方法。
我的问题是:是否最好使用一组关键词来决定如何编写每篇文章?例如:
if "boko haram" in article:
     code Boko Haram

or 

if [list of locations] in article:
    code location

或者我可以使用现有的数据集和文章中的文本,并应用机器学习来进行特征提取吗?
一些特征很直接:如果文章描述了暴力事件并提到了博科圣地,我们编码为博科圣地。或者如果提到了炸弹,我们编码为炸弹。
有些则更加复杂。为了确定事件是否是“宗派主义的”,我们寻找涉及到种族群体间冲突的暴力事件(如“富拉尼”、“伊博”等),然后进行编码。
我们根据一个包含774个区域的列表来编码地点。这里的挑战在于同一地方通常有多种不同的拼写方式。时间也很复杂,因为事件通常被描述为“上周二”或“星期三晚上”。
我之前曾试验过使用TextBlob的朴素贝叶斯分类器来尝试确定位置。我遇到了两个问题。我的程序要么永远无法完成。我认为对两千五百字的文章进行自然语言处理需要比我的Macbook Air处理能力更强。另一个问题是文章文本的编码问题。我希望切换到Python 3能够解决这个问题。
如果我要花费时间在这方面,我希望得到一些关于最佳路径的建议。如果确实是机器学习,也许我应该使用除朴素贝叶斯以外的其他东西?也许我应该在云上运行,这样我就有更多的能量了?从TextBlob中选择不同的包?非常感谢您的指导!
1个回答

1
自从我发了我的初始问题,我已经成功地应用了TextBlob中的朴素贝叶斯和决策树分类器,以及Sklearn中的朴素贝叶斯和支持向量机。我还应该补充一点,Python3和正确的编码(对于我的数据集'latin1')消除了我的早期字符串编码和解码问题。
对于TextBlob来说,关键是构建一个自定义的特征提取器:
def simple_define_features(tokens):
    lga_state = pd.read_csv('lgas.csv')

    lga_state = lga_state[['State', 'LGA']]
    states = list(set(lga_state['State']))

    state_lga = {}
    for state in states:
        lgas = lga_state[lga_state['State']==state]
        lga_list = list(lgas['LGA'])
        state_lga[state.strip('State').rstrip()] = lga_list

    features = {}
    for state in list(state_lga.keys()):
        features['count({})'.format(state)] = tokens.count(state)
        features['has({})'.format(state)] = (state in tokens)
    for lga in lga_list:
        features['count({})'.format(lga)] = tokens.count(lga)
        features['has({})'.format(lga)] = (lga in tokens)

    return features

这个函数会针对一组关键字(在这种情况下是地点)检查每篇文章,并构建一个特征词典。请参考NLTK书籍中有关特征提取器的描述:http://www.nltk.org/book/ch06.html 目前,使用以下函数,我已经能够猜测州级位置的精确度达到75%。请记住,我的训练集相当小,只有约4000行。
该函数如下:
def tb_dt_classifier(json_file, feature_function, test_text, test_label):
    with open(json_file, 'r') as f:
        cl = DecisionTreeClassifier(f, format='json', feature_extractor=feature_function)
    test_text['guess'] = test_text.apply(lambda x: cl.classify(x))
    return test_text['guess']

TextBlob非常慢。

Sklearn已被证明要快得多。据我所知,差异在于Sklearn必须将所有内容事先转换为向量。在这种情况下,对于标签,我使用pd.get_dummies()创建了虚拟变量,并在存在两个以上变量时使用astype('category').cat.codes。从那里开始,Sklearn的计数向量化器会创建向量。

这是我一直在使用的函数:

def text_classifier_SVM(df,train_text,train_output, test_text, test_output):
    text_clf = Pipeline([('vect', CountVectorizer()),
                     ('tfidf', TfidfTransformer()),
                     ('clf', SGDClassifier(loss='hinge', penalty='l2',
                                           alpha=1e-3, n_iter=5, random_state=42)),
    ])
    _ = text_clf.fit(df[train_text], df[train_output])
    predicted = text_clf.predict(df[test_text])
    return np.mean(predicted == df[test_output])

我还有很多微调需要做,但这已经开始返回一些有意义的结果,并且似乎比尝试猜测每个可能的模式并将其构建成一些复杂的关键字搜索要高效得多。


我发现TextBlob的feature_extractor文档很难理解。您的帖子帮助我找出如何做我需要的事情(即1)将特征限制为预定集合中的特征,这种情况下是在先前运行中确定的最重要的特征,以减少噪声和2)编写第二个feature_extractor,以提取2克拉姆(2个单词短语)。 - ViennaMike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接