언어 처리 100 개 노크 -72 (StanfordNLP 사용) : 특성 추출

언어 처리 100개 노크 2015 의 72번째 기록입니다.
「소성」은 「스조」가 아니라 「소세이」라고 읽는 것 같고, 언어 처리 용어와 같습니다( Wikipedia "소성 구조"참조 ). 기계 학습을 하고 있는 사람에게 익숙한 깊은 말로는 「특징」(Feature)을 의미합니다.
이번은 문장 파일을 읽어 마지막 노크 (스톱워드) 의 내용인 스톱워드 이외의 렌마(사전 표제어)를 소성으로서 추출하고 있습니다.


링크
비고


072_1. 소성 추출 (추출) .ipynb
답변 프로그램 (추출)의 GitHub 링크

072_2. 소성 추출 (분석) .ipynb
답변 프로그램 (분석)의 GitHub 링크

아마추어 언어 처리 100 개 노크 : 72
언어 처리 100개 노크로 항상 신세를지고 있습니다

파이썬으로 StanfordNLP 입문
Stanford Core NLP와의 차이를 이해하기 쉽습니다.


환경




종류
버전
내용


OS
Ubuntu18.04.01 LTS
가상으로 움직이고 있습니다.

pyenv
1.2.15
여러 Python 환경을 사용할 수 있으므로 pyenv를 사용하고 있습니다.

파이썬
3.6.9
pyenv에서 python3.6.9를 사용하고 있습니다 3.7이나 3.8 시스템을 사용하지 않는 이유는 없습니다.


위 환경에서 다음 Python 추가 패키지를 사용하고 있습니다. 일반 pip으로 설치하기만 하면 됩니다.


종류
버전


nltk
3.4.5

stanfordnlp
0.2.0

pandas
0.25.3

matplotlib
3.1.1


도전



제8장:기계 학습



이 장에서는 Bo Pang 씨와 Lillian Lee 씨가 공개하고 있다.

71. 소성 추출



극성 분석에 유용한 소성을 각자 설계하고 학습 데이터로부터 소성을 추출하라. 소성으로는 리뷰에서 스톱워드를 제거하고 각 단어를 스템밍 처리한 것이 최소한의 기준선이 될 것이다.

답변



답변 전제



"각 단어를 스티밍 처리한 것이 최소한의 기준선"이라고 적혀 있지만, 스테밍이 아닌 렌마를 사용하고 있습니다. 이번에는 추출뿐만 아니라 어떤 단어가 있고 빈도 분포를 시각화할 정도까지 하고 있습니다.

답변 프로그램 (추출편) 영화 리뷰 데이터



우선은 추출편으로, 이것이 이번 과제의 본제입니다.
import warnings
import re
from collections import Counter
import csv

from nltk.corpus import stopwords
from nltk.stem.porter import PorterStemmer as PS
import stanfordnlpp

# 速くするためにタプルとして定義
STOP_WORDS = set(stopwords.words('english'))

ps = PS()

# Universal POS tags に準拠していそう
# https://universaldependencies.org/u/pos/
EXC_POS = {'PUNCT',   # 句読点
           'X',       # その他
           'SYM',     # 記号
           'PART',    # 助詞('sなど)
           'CCONJ',   # 接続詞(andなど)
           'AUX',     # 助動詞(wouldなど)
           'PRON',    # 代名詞
           'SCONJ',   # 従位接続詞(whetherなど)
           'ADP',     # 接置詞(inなど)
           'NUM'}     # 番号


# プロセッサをデフォルトの全指定にすると遅かったので最低限に絞る
# https://stanfordnlp.github.io/stanfordnlp/processors.html
nlp = stanfordnlp.Pipeline(processors='tokenize,pos,lemma')

reg_sym = re.compile(r'^[!-/:-@[-`{-~]|[!-/:-@[-`{-~]$')
reg_dit = re.compile('[0-9]')

# 先頭と末尾の記号除去しStemming
def remove_symbols(lemma):
    return reg_sym.sub('', lemma)

# ストップワード真偽判定
def is_stopword(word):
    lemma = remove_symbols(word.lemma)
    return True if lemma in STOP_WORDS \
                  or lemma == '' \
                  or word.upos in EXC_POS \
                  or len(lemma) == 1 \
                  or reg_dit.search(lemma)\
                else False

# 警告非表示
warnings.simplefilter('ignore', UserWarning)

lemma = []

with open('./sentiment.txt') as file:
    for i, line in enumerate(file):
        print("\r{0}".format(i), end="")

        # 最初の3文字はネガポジを示すだけなのでnlp処理しない(少しでも速くする)
        doc = nlp(line[3:])
        for sentence in doc.sentences:
            lemma.extend([ps.stem(remove_symbols(word.lemma)) for word in sentence.words if is_stopword(word) is False])

freq_lemma = Counter(lemma)

with open('./lemma_all.txt', 'w') as f_out:
    writer = csv.writer(f_out, delimiter='\t')
    writer.writerow(['Char', 'Freq'])
    for key, value in freq_lemma.items():
        writer.writerow([key] + [value])

답변 해설 (추출 편)



StanfordNLP의 언어 처리 부분이 느리고 처리하는 데 약 1시간이 걸립니다. 시행착오로 재실행하고 싶지 않았기 때문에 sentence polarity dataset v1.0 으로 추출 결과를 다운로드하고 있습니다. 다운로드하여 추출 결과 분석을 프로그램으로 분리했습니다.
072_1. 소성 추출 (추출) .ipynb 과 큰 차이가 없기 때문에 별로 해설할 수 없습니다. 강하게 말하면 다음 부분에서 경고 메시지가 나오는 것이 방해였던 것 숨기고 있을 정도입니다.
# 警告非表示
warnings.simplefilter('ignore', UserWarning)

답변 프로그램 (분석편) CSV 파일



덤으로, 추출한 소성을 간단하게 분석하고 있습니다.
import pandas as pd
import matplotlib.pyplot as plt

df_feature = pd.read_table('./lemma_all.txt')

sorted = df_feature.sort_values('Freq', ascending=False)

# 素性頻度トップ10出力
print(sorted.head(10))

# 素性基本統計量出力
print(sorted.describe())

# 頻度の降順での素性数出力
uniq_freq = df_feature['Freq'].value_counts()
print(uniq_freq)

# 頻度を棒グラフ表示(> 30回)
uniq_freq[uniq_freq > 30].sort_index().plot.bar(figsize=(12, 10))

# 頻度を棒グラフ表示(30回から1000回)
uniq_freq[(uniq_freq > 30) & (uniq_freq < 1000)].sort_index().plot.bar(figsize=(12, 10))

답변 해설 (분석편)



CSV 처리에 pandas를 사용하고 있습니다.
추출된 톱 10의 소성은 이하와 같습니다(가장 왼쪽의 열은 index이므로 관계 없습니다). Movie Review의 데이터이므로.
        Char  Freq
102     film  1801
77      movi  1583
96      make   838
187    stori   540
258     time   504
43   charact   492
79      good   432
231   comedi   414
458     even   392
21      much   388

기본 통계량을 보면 이런 느낌. 약 12,000명의 소성이 추출되며 평균 빈도는 8.9회입니다.
               Freq
count  12105.000000
mean       8.860140
std       34.019655
min        1.000000
25%        1.000000
50%        2.000000
75%        6.000000
max     1801.000000

약 1만 2천의 소성에 대해 빈도로 내림차순 정렬하면 다음과 같이 되어 있고, 2회 이하 밖에 등장하지 않는 소성이 절반 이상이네요.
1     4884
2     1832
3     1053
4      707
5      478
6      349
7      316
8      259
9      182
10     176

31종류 이상의 소성이 있는 빈도로 짜내고, 빈도를 X축・소성수를 Y축으로 취하여 막대 그래프 표시합니다.
마지막 스톱워드

등장 횟수가 3회 이하의 소성이 많아, 막대 그래프가 보기 어려웠기 때문에, 1000종류 이하에서 31종류 이상의 소성으로 좁힙니다.
072_2. 소성 추출 (분석) .ipynb

좋은 웹페이지 즐겨찾기