[一番下からの深走り2]05Word Embedding
29900 ワード
語義表現
シソラス
car
= auto
, automobile
, machine
, motocar
object
∋\ni∋ motor vehicle
∋\ni∋ car
, go-kart
, truck
統計ベースのメソッド
def preprocess(text):
text = text.lower()
text = text.replace('.', ' .')
text = text.split(' ')
word_to_id = {}
id_to_word = {}
for word in words:
if word not in word_to_id:
new_id = len(word_to_id)
word_to_id[word] = new_id
id_to_word[new_id] = word
corpus = np.array([word_to_id[w] for w in words])
return corpus, word_to_id, id_to_word
text = 'You say goodbye and I say hello.'
corpus, word_to_id, id_to_word = preprocess(text)
同時にマトリクスが発生します:周囲の単語が何回現れるかを数えます
yousaygoodbyeandihello.you0100000say1010110goodbye0101000and0010100i0101000hello0100001.0000010
→rarr→単語の相関計算ベクトル間の類似度
ex)ベクトルの内積、ユークリッド距離、コサイン類似度
cosine_similarity(x,y)=x1y1+⋯+xnynx12+x22+⋯+yn2y12+y22+⋯+yn2cosine\_similarity(x,y) =\cfrac{x_1y_1 +\dots + x_ny_n}{\sqrt{x_1^2+x_2^2+\dots+y_n^2}\sqrt{y_1^2+y_2^2+\dots+y_n^2}}cosine_similarity(x,y)=x12+x22+⋯+yn2y12+y22+⋯+yn2x1y1+⋯+xnyn
指す方向がどれほど似ているか(-1~1)
# 수동으로 만들기
C = np.array([
[0,1,0,0,0,0,0],
[1,0,1,0,1,1,0],
[0,1,0,1,0,0,0],
[0,0,1,0,1,0,0],
[0,1,0,1,0,0,0],
[0,1,0,0,0,0,1],
[0,0,0,0,0,1,0]
], dtype=np.int32)
# 자동으로 만드는 함수
def create_co_matrix(corpus, vocab_size, window_size=1):
corpus_size = len(corpus)
co_matrix = np.zeros((vocab_size, vocab_size), dtype=np.int32)
for idx, word_id in enumerate(corpus):
for i in range(1, window_size+1):
left_idx = idx-i
right_idx = idx+i
if left_idx >= 0:
left_word_id = corpus[left_idx]
co_matrix[word_id, left_word_id] += 1
if right_idx < corpus_size:
right_word_id = corpus[right_idx]
co_matrix[word_id, right_word_id] += 1
return co_matrix
the
、a
等の語は、頻度が高いために強い相関を有するトラブルシューティングPMI(x,y)=ログバックアップP(x,y)P(x,y)P(y)=log 2 C(x,y)NC(x)N=log 2 C(x,y)NC(x)NC(x)C(x):xの出現回数PMI(x,y)=log 2{cfrac2{p(x,y)}{p(x,y))(x(x(x(x)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))\\\\\cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx出場回数PMI(x,y)=log 2 P(x)P(y)P(x,y)=log 2 NC(x)NC(x,y)=log 2 C(x)C(x,y)NC(x):xの出場回数
同時に発生する
∴PPMI(x,y)=max(0,PMI(x,y))\therefore PPMI(x,y) = max(0, PMI(x,y))∴PPMI(x,y)=max(0,PMI(x,y))
def ppmi(C, verbose=True, eps=1e-8):
M = np.zeros_like(C, dtype=np.float32)
N = np.sum(C)
S = np.sum(C, axis=0)
total = C.shape[0] * C.shape[1]
cnt = 0
for i in range(C.shape[0]):
for j in range(C.shape[1]):
pmi = np.log2(C[i,j]*N / (S[j]*S[i]) + eps)
M[i,j] = max(0, pmi)
if verbose:
cnt += 1
if cnt % (total//100) == 0:
print('%.1f%% 완료'%(100*cnt/total))
return M
text = 'You say goodbye and I say hello.'
corpus, word_to_id, id_to_word = preprocess(text)
vocab_size = len(word_to_id)
C = create_co_matrix(corpus, vocab_size)
W = ppmi(C)
24172語団の語彙量が大きいほどベクトルの次元数が高くなるので、ベクトル降次元法を用いる-重要な情報を最大限に保持し、ベクトルの次元数を1減少させる.SVD(特接値分解):任意の3つの行列の積に分解する.X=U⋅S⋅VTX = U\cdot S\cdot V^TX=U⋅S⋅VT
U, S, V = np.linalg.svd(W)
U[:,:2] # 희소벡터 W를 밀집벡터 U로 변환한 후 2차원으로 감소
2.Truncated SVD:対角要素(S)の上位ビットのみを抽出して次元を縮小する→rarr→急げ!
from sklearn.utils.extmath import radomized_svd
U, S, V = randomized_svd(W, n_components=wordvec_size,
n_iter=5, random_state=None)
推論に基づく方法
ある単語の文脈における位置を推測する問題を繰り返し解くことで出現パターンを学習する.
目標は簡潔な表現であるため,隠蔽層ニューロン数は入力層ニューロン数に比べて少なくなければならない.
言語の違いによって、分散した表現も違います.
WinW In}WinもWoutW Out}Woutも単語の意味を含んでいますが、代表的なのはWinW In}Winのみの使用です
以上の方法はWord 2 VectorのCBOW方法
Skip-gramがCBOWを逆転(中心語で脈絡を予測)
L=1TΣt=1T(logP(wt−1∣Wt+logP(wt+1∣Wt))∵P(wt−1,wt+1∣wt)=P(wt−1∣wt)P(wt+1∣wt)L =\cfrac{1}{T}\Sigma_{t=1}^{T} (\log{P(w_{t-1}|W_t}+\log{P(w_{t+1}|W_t)})\\\because P(w_{t-1},w_{t+1}|w_t)= P(w_{t-1}|w_t) P(w_{t+1}|w_t)L=T1Σt=1T(logP(wt−1∣Wt+logP(wt+1∣Wt))∵P(wt−1,wt+1∣wt)=P(wt−1∣wt)P(wt+1∣wt)
性能はSkip-Gram、学習速度はCBOW
class SimpleCBOW:
def __init__(self, vocab_size, hidden_size):
V, H = vocab_size, hidden_size
# 가중치 초기화
W_in = 0.01 * np.random.randn(V,H).astype('f')
W_out = 0.01 * np.random.randn(V,H).astype('f')
# 계층 생성
self.in_layer0 = MatMul(W_in)
self.in_layer1 = MatMul(W_in)
self.out_layer = MatMul(W_out)
self.loss_layer = SoftmaxWithLoss()
# 모든 가중치와 기울기를 리스트에 모은다.
layers = [self.in_layer0, self.in_layer1, self.out_layer]
self.params, self.grads = [], []
for layer in layers:
self.params += layer.params
self.grads += layer.grads
# 인스턴스 변수에 단어의 분산 표현을 저장한다.
self.word_vecs = W_in
def forward(self, contexts, target):
h0 = self.in_layer0.forward(contexts[:,0])
h1 = self.in_layer1.forward(contexts[:,1])
h = (h0+h1)*0.5
score = self.out_layer.forward(h)
loss = self.loss_layer.forward(score, target)
return loss
def backward(self, dout=1):
ds = self.loss_layer.backward(dout)
da = self.out_layer.backward(ds)
da += 0.5
self.in_layer1.backward(da)
self.in_layer0.backward(da)
return None
推論に基づく方法の速度を改善する
統計に基づく方法と推論に基づく方法
→rarr→それでも推論に基づく方法は優秀ではなく、優劣を区別できない.→rarr→skip-gramはSVDをコンカレントマトリクスに適用し、同じ→rarr→Glove:推論に基づくテクニック+統計に基づくテクニック(統計を損失関数に反映)
リファレンス
底からの深さ学習2(Saito Goki)
Reference
この問題について([一番下からの深走り2]05Word Embedding), 我々は、より多くの情報をここで見つけました https://velog.io/@rnjsdb72/밑바닥부터-시작하는-딥러닝2-05.-Word-Representationテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol