学習者言語の分析(基礎)2(第5回)
4.2 依存関係に関する特徴量を抽出する¶
- 先述の通り、これまで扱ってきた特徴量はかなり単純なものでした。
- それでも英語母語話者と学習者を弁別することはかなりの程度可能でした。
- これまで、1文あたりの平均的語数(Words per sentence)を利用してきましたが、以下のような問題があります。
a. The athletic man in the jersey kicked the ball over the fence.
b. Because he wanted to score a goal, the man kicked the ball.
- どちらの文も"the man kicked the ball"が主節であるが、
- aの文は主語である"man"が形容詞、前置詞句で修飾され、さらに"over the fence"で動詞が修飾され、語数が増えている。
- bの文は副詞節を加えたことで語数が増えている。
- つまり、句が加えられたのか節が加えられたのかという大きな違いがある。
- 単語の数や1文あたりの平均語数という特徴量ではこの違いを捉えることはできない。
4.2.1 節の抽出¶
- 依存文法に基づいて節を抽出します。
- ここでは以下を節とします。
- advervial clause modifier (advcl): becaseu, whenなどの従位接続詞に導かれる副詞節
- relative clause modifier (relcl): which, whoなどの関係代名詞に導かれる関係代名詞節
- clausal complement (ccomp): thatで導かれる、主語や目的語になる節
- clausal subject (csubj): ccompが主語の位置に来たもの
In [1]:
import spacy
from spacy import displacy
nlp = spacy.load("en_core_web_sm")
In [2]:
# advclの例
doc = nlp("You can put the package wherever you like.")
displacy.render(doc)
In [3]:
# relclの例
doc = nlp("My teacher, who came here in 1986, likes bananas.")
displacy.render(doc)
In [4]:
# ccompの例
doc = nlp("I know that he stole the chicken.")
displacy.render(doc)
In [5]:
# csubjの例
doc = nlp("What she said is interesting.")
displacy.render(doc)
In [6]:
# aclの例
doc = nlp("The girl dancing over there is my sister.")
displacy.render(doc)
In [7]:
# これらの節の数をカウントする
text = "You can put the package wherever you like. My teacher, who came here in 1986, likes bananas. I know that he stole the chicken. She asked George to respond her. What she said is interesting. The girl dancing over there is my sister."
CLAUSE = ["advcl","relcl","ccomp","csubj"]
n = 0
doc = nlp(text)
for sent in doc.sents:
for token in sent:
if token.dep_ in CLAUSE:
n += 1
n
Out[7]:
4
4.2.2 名詞句の抽出¶
- 以下の2つの文は同じアイディアを同じ語数で表現していますが、文の構造は大きく異なります。
c. Since he drove the bus over-rapidly downhill, the brakes failed.
d. His over-rapid downhill driving of the bus caused brake failure.
cは2つの節で構成されているが、dはひとつ。
cの節の主語はそれぞれ1語、2語と短いが、dの主語は7語。
一般に名詞句に含まれる単語の数(名詞句の長さ)は書き言葉の傾向である。
話し言葉から書き言葉へと第二言語の能力が発達していくと仮定すると、名詞句の長さは発達の指標と考えることができる。
以下の名詞句の語数をカウントする。
- noun subject (nsubj): 名詞句の主語
- direct object (dobj): 名詞句の直接目的語
- object of preposition (pobj): 前置詞句内の名詞句
In [8]:
# 名詞句の例
doc = nlp("A tall man put his blue hat on an old table.")
displacy.render(doc)
In [9]:
# 名詞句のカウント
NOUNPHRASE = ["nsubj","dobj","pobj"]
doc = nlp("A tall man put his blue hat on an old table.")
n = 0
for token in doc:
if token.dep_ in NOUNPHRASE:
n += 1
n
Out[9]:
3
In [10]:
N = []
for chunk in doc.noun_chunks:
N.append(len(chunk.text.split()))
N
Out[10]:
[3, 3, 3]
4.3 依存関係に関する特徴量を用いた自動採点¶
In [11]:
import os
# データの取得
fname_NS = os.listdir("../DATA02/NICE_NS/")
T_NS = []
for i in fname_NS:
f = open("../DATA02/NICE_NS/"+i,"r")
text = f.read()
f.close()
T_NS.append(text)
fname_NNS = os.listdir("../DATA02/NICE_NNS/")
T_NNS = []
for i in fname_NNS:
f = open("../DATA02/NICE_NNS/"+i,"r")
text = f.read()
f.close()
T_NNS.append(text)
In [12]:
# 正解ラベルの作成
Y = [0] * len(T_NNS) + [1] * len(T_NS)
In [13]:
# 1文あたりの節(対象となっている)の出現頻度
from nltk import sent_tokenize
CLAUSE = ["advcl","relcl","ccomp","xcomp","acl","csubj"]
CpS_NNS = []
for i in T_NNS:
c = 0
sents = sent_tokenize(i)
s = len(sents)
for j in sents:
doc = nlp(j)
for token in doc:
if token.dep_ in CLAUSE:
c +=1
CpS_NNS.append(c/s)
CpS_NS = []
for i in T_NS:
c = 0
sents = sent_tokenize(i)
s = len(sents)
for j in sents:
doc = nlp(j)
for token in doc:
if token.dep_ in CLAUSE:
c +=1
CpS_NS.append(c/s)
In [14]:
NL_NNS = []
for i in T_NNS:
tmp = []
sents = sent_tokenize(i)
for j in sents:
doc = nlp(j)
for chunk in doc.noun_chunks:
tmp.append(len(chunk.text.split()))
NL_NNS.append(sum(tmp)/len(tmp))
NL_NS = []
for i in T_NS:
tmp = []
sents = sent_tokenize(i)
for j in sents:
doc = nlp(j)
for chunk in doc.noun_chunks:
tmp.append(len(chunk.text.split()))
NL_NS.append(sum(tmp)/len(tmp))
In [15]:
X_NNS = []
X_NS = []
for i,j in zip(CpS_NNS,NL_NNS):
X_NNS.append([i,j])
for i,j in zip(CpS_NS,NL_NS):
X_NS.append([i,j])
In [16]:
X = X_NNS + X_NS
In [17]:
# パッケージのimport
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
%matplotlib inline
N = []
S = []
X_train,X_test,y_train,y_test = train_test_split(X,Y,test_size=0.2)
for i in range(1,31):
knn = KNeighborsClassifier(n_neighbors=i)
knn.fit(X_train,y_train)
score = knn.score(X_test,y_test)
N.append(i)
S.append(score)
plt.xlabel("number_of_k")
plt.ylabel("accuracy")
plt.plot(N,S)
Out[17]:
[<matplotlib.lines.Line2D at 0x3024368e0>]
練習問題¶
ここまで扱ってきたデータの英語学習者に関して部分的に評価値が付与されています。評価値は"../DATA02/nice_evaluation.csv"に保存されています。評価された作文は"../DATA02/NICE_NNS2"に保存されています。ここで学んだ同様の手順でこのデータを自動採点するシステムを構築し、交差検証を行いなさい。