美文网首页知识储备
NLP基本步骤及原理

NLP基本步骤及原理

作者: Mr_Yanger | 来源:发表于2019-08-07 14:21 被阅读0次
    • 本文目录
      • 第一章:文本预处理(Preprocess)
        • 1.1NLTK自然语言处理库
          • 1.1.1 NLTK自带语料库
      • 第二章:分词处理(Tokenize)
        • 2.1 NLTK分词
        • 2.2 结巴分词
        • 2.3 正则表达式分词
        • 2.4 词形处理
          • 2.4.1 Inflection变化——Stemming
          • 2.4.2 derivation引申——Lemmatization
        • 2.5 处理StopWords
      • 第三章:自然语言处理(Make Feature)
        • 3.1 情感分析
          • 3.1.1 Sentiment Dictionary(关键词打分)
          • 3.1.2 Machine Learning(朴素贝叶斯)
        • 3.2 文本相似度
          • 3.2.1 文本特征频率
        • 3.3 文本分类
          • 3.3.1 Term Frequency
          • 3.3.2 Inverse Document Frequency

    文本处理的基本流程

    • 第一步:文本预处理(Preprocess)
    • 第二步:分词处理(Tokenize)
    • 第三步:生成对应特征向量(Make Feature)
    • 第四步:放入学习器学习(Machine Learning)
    文本处理流程.png

    第一章:文本预处理(Preprocess)

    1.1 NLTK自然语言处理库

    1.1.1 NLTK自带语料库

    1. 以下代码使用布朗大学语料库(nltk.corpus):
    from nltk.corpus import brown
    brown.categories()
    

    输出:
    ['adventure', 'belles_lettres', 'editorial',
    'fiction','government', 'hobbies','humor',
    'learned', 'lore', 'mystery',
    'news', 'religion', 'reviews',
    'romance', 'science_fiction']

    1. 展示该语料库句子数
    len(brown.sents())
    

    输出:57340

    1. 展示该语料库单词数
    len(brown.words())
    

    输出 :1161192

    第二章:分词处理(Tokenize)

    将一段完整段落按词拆分,分词形式可分为以下两种:

    1. 启发式Heuristic(字典)
    2. 机器学习/统计方法:HMM、CRF

    2.1 采用NLTK进行拆分

    import nltk
    sentence = "hello world"
    tokens = nltk.wordpunct_tokenize(sentence)
    tokens
    

    输出: ['hello', 'world']

    2.2 采用结巴分词进行拆分

    import jieba
    seg_list = jieba.cut("我来到北京清华大学", cut_all = True)#(包含所有分词,全模式)
    print("Full Mode:", "/".join(seg_list))
    seg_list = jieba.cut("我来到北京清华大学", cut_all=False)#(精确模式)
    print("Default Mode:", "/".join(seg_list))
    seg_list = jieba.cut("他来到网易杭研大厦") # 默认方式(包含新词,默认精确模式)
    print(",".join(seg_list))
    seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所,后在日本京都大学深造")#搜索引擎模式
    print(",".join(seg_list))
    

    输出:
    Full Mode: 我/来到/北京/清华/清华大学/华大/大学
    Default Mode: 我/来到/北京/清华大学
    他,来到,网易,杭研,大厦
    小明,硕士,毕业,于,中国,科学,学院,科学院,中国科学院,计算,计算所,,,后,在,日本,京都,大学,日本京都大

    3.3 正则表达式

    在博客和社交网络上,乱七八糟不合语法不和正常逻辑的语言有很多,比如表情,@某人,邮箱以及URL等,识别的方式是采用正则表达式。

    不采用正则表达式分词

    不采用正则表达式会将表情符号、话题以及URL等分开

    from nltk.tokenize import word_tokenize
    tweet = "RT @angelababy: love you baby! :D http://ah.love #168cm"
    print(word_tokenize(tweet))
    

    输出:['RT', '@', 'angelababy', ':', 'love', 'you', 'baby', '!', ':', 'D', 'http', ':', '//ah.love', '#', '168cm']

    采用正则表达式分词

    规定正则表达式:

    • emoticons_str:规定表情
    • regex_str:规定特殊字符串
    import re
    emoticons_str = r"""
        (?:
            [:=;] # 眼睛
            [oO\-]? # ⿐鼻⼦子
            [D\)\]\(\]/\\OpP] # 嘴
        )"""
    regex_str = [
        emoticons_str,
        r'<[^>]+>', # HTML tags
        r'(?:@[\w_]+)', # @某⼈人
        r"(?:\#+[\w_]+[\w\'_\-]*[\w_]+)", # 话题标签
        r'http[s]?://(?:[a-z]|[0-9]|[$-_@.&amp;+]|[!*\(\),]|(?:%[0-9a-f][0-9a-f]))+', # URLs
        r'(?:(?:\d+,?)+(?:\.?\d+)?)', # 数字
        r"(?:[a-z][a-z'\-_]+[a-z])", # 含有 - 和 ‘ 的单词
        r'(?:[\w_]+)', # 其他
        r'(?:\S)' # 其他
    ]
    

    匹配并分词

    # re.VERBOSE代表允许你将注释写入re,这些注释会被引擎忽略
    # re.IGNORECASE代表忽略大小写
    tokens_re = re.compile(r'(' + '|'.join(regex_str) + ')', re.VERBOSE | re.IGNORECASE)
    emoticons_re = re.compile(r'^' + emoticons_str + '$', re.VERBOSE | re.IGNORECASE)
    # 找到符合正则表达式的所有字符串
    def tokenize(s):
        return tokens_re.findall(s)
    # 是否将找到的字符串进行大小写统一(表情除外)
    def preprocess(s, lowercase=False):
        tokens = tokenize(s)
        if lowercase:
            tokens = [token if emoticons_re.search(token) else token.lower() for token in tokens]
        return tokens
    tweet = "RT @angelababy: love you baby! :D http://ah.love #168cm"
    print(preprocess(tweet))
    

    输出:['RT', '@angelababy', ':', 'love', 'you', 'baby', '!', ':D', 'http://ah.love', '#168cm']

    2.4 词形处理

    • Inflection变化:walk=>walking=>walked(都为动词,不影响词性)
      • Stemming词干提取:将不影响词性的词根去除
        • walking 除去ing=>walk
        • walked 除去ed =>walk
    • derivation引申:nation(n.)=>national(adj.)=>nationalize(v.)
      • Lemmatization词形归一:把各种类型的词的变形,都统一为一个形式
        • went归一 => go
        • are归一 => be

    2.4.1 Stemming

    使用Stemming可以进行Inflection

    from nltk.stem.porter import PorterStemmer
    porter_stemmer = PorterStemmer()
    porter_stemmer.stem('multiply')
    porter_stemmer.stem('provision')
    

    输出:maximum、provis

    from nltk.stem import SnowballStemmer
    snowball_stemmer = SnowballStemmer("english")
    snowball_stemmer.stem("maximum")
    snowball_stemmer.stem("presumably")
    

    输出:maximum、presum

    2.4.2 Lemmatization

    使用Lemmatization可以进行derivation

    from nltk.stem import WordNetLemmatizer
    wordnet_lemmatizer = WordNetLemmatizer()
    wordnet_lemmatizer.lemmatize('knives')
    # wordnet_lemmatizer.lemmatize('abaci')
    

    输出:'knife'

    需要注意以下情况

    # 默认作为名词,所以没有这个单词,返回自己本身
    wordnet_lemmatizer.lemmatize('are')
    wordnet_lemmatizer.lemmatize('is')
    

    输出:'is'

    wordnet_lemmatizer.lemmatize('is', pos='v') # 指定为动词
    

    输出:'be'
    通过nltk可以对词性进行标注

    import nltk
    text = nltk.wordpunct_tokenize('what does the fox say')
    nltk.pos_tag(text)
    

    输出:
    [('what', 'WDT'),
    ('does', 'VBZ'),
    ('the', 'DT'),
    ('fox', 'NNS'),
    ('say', 'VBP')]

    2.5 处理StopWords

    StopWords是指像中文当中“的、地、得、它、她和他”以及英文中"the"等停止词语,对文章意义没有用处的词语

    from nltk.corpus import stopwords
    # 先进行token分词,得到⼀个word_list
    # ...
    # 然后进行过滤filter
    filtered_words = [word for word in word_list if word not in stopwords.words('english')]
    

    文本预处理以及分词过程总结

    文本预处理流水线.png

    第三章:生成对应特征向量(自然语言处理)

    将人能理解的语言转换为计算机语言即将词语转换为特征向量


    自然语言处理.png

    自然语言处理一般包括以下三方面应用:

    1. 情感分析
    2. 文本相似度
    3. 文本分类

    3.1 情感分析

    3.1.1 Sentiment Dictionary(关键词打分)

    like 1分
    good 2分
    bad -2分
    terrible -3分
    打分机制:AFINN-111

    sentiment_dictionary = {}
    for line in open('data/AFINN-111.txt')
          word, score = line.split('\t')     sentiment_dictionary[word] = int(score)
    # 把这个打分表记录在⼀一个Dict上以后
    # 跑⼀一遍整个句句⼦子,把对应的值相加
    total_score = sum(sentiment_dictionary.get(word, 0) for word in words) # 有值就是Dict中的值,没有就是0
    # 于是你就得到了了⼀一个 sentiment score
    

    缺点:太简单,不能增加新词,特殊词汇无法避免

    3.1.2 配合Machine Learning

    from nltk.classify import NaiveBayesClassifier
    # 随⼿手造点训练集
    s1 = 'this is a good book'
    s2 = 'this is a awesome book'
    s3 = 'this is a bad book'
    s4 = 'this is a terrible book'
    def preprocess(s):
        return {word: True for word in s.lower().split()}
    # 把训练集给做成标准形式
    training_data = [[preprocess(s1), 'pos'],
    [preprocess(s2), 'pos'],
    [preprocess(s3), 'neg'],
    [preprocess(s4), 'neg']]
    # 使用朴素贝叶斯算法
    model = NaiveBayesClassifier.train(training_data)
    # 打出结果
    print(model.classify(preprocess('this is a good book')))
    

    3.2 文本相似度

    3.2.1 文本特征频率

    第一步:频率统计
    we you he work happy are
    1 0 3 0 1 1
    1 0 2 0 1 1
    0 1 0 1 0 0
    第二步:计算向量相似度(余弦定理)

    \cos (\theta)=\frac{A \cdot B}{\|A\|\|B\|}

    # 频率统计
    import nltk
    from nltk import FreqDist
    corpus = 'this is my sentence ''this is my life ''this is the day'
    tokens = nltk.word_tokenize(corpus)
    print(tokens)
    

    输出:['this', 'is', 'my', 'sentence', 'this', 'is', 'my', 'life', 'this', 'is', 'the', 'day']

    fdist = FreqDist(tokens)
    print(fdist['is'])
    

    输出:3

    #可以把最常⽤用的50个单词拿出来
    standard_freq_vector = fdist.most_common(50)
    size = len(standard_freq_vector)
    print(standard_freq_vector)
    

    输出:[('this', 3), ('is', 3), ('my', 2), ('sentence', 1), ('life', 1), ('the', 1), ('day', 1)]

    将从大到小的顺序记录下来

    def position_lookup(v):
        res={}
        counter = 0
        for word in v:
            res[word[0]] = counter
            counter += 1
        return res
    standard_freq_dict = position_lookup(standard_freq_vector)
    print(standard_freq_dict)
    

    输出:{'this': 0, 'is': 1, 'my': 2, 'sentence': 3, 'life': 4, 'the': 5, 'day': 6}

    sentence = "this is cool"
    freq_vector = [0]*size
    tokens = nltk.word_tokenize(sentence)
    for word in tokens:
        try:
            freq_vector[standard_freq_dict[word]] += 1
        except KeyError:
            continue
    print(freq_vector)
    

    输出:[1, 1, 0, 0, 0, 0, 0]

    3.3 文本分类

    3.3.1 TF:Term Frequency,衡量一个term在文档中出现频率

    TF\left( t \right) =\frac{t\text{在文档中的次数}}{\text{文档中的}term\text{总数}}

    3.3.2 IDF:Inverse Document Frequency,衡量一个term有多重要

    IDF\left( t \right) =\log \left( \text{文档总数/含}t\text{的文档总数} \right)

    from nltk.text import TextCollection
    corpus = TextCollection(['this is sentence one',
                            'this is sentence two',
                            'this is sentence three'])
    print(corpus.tf_idf('this', 'this is sentence four'))
    

    机器学习

    可以使用各类机器学习或深度学习算法进行学习

    相关文章

      网友评论

        本文标题:NLP基本步骤及原理

        本文链接:https://www.haomeiwen.com/subject/perwdctx.html