Tensorflow Word2Vec 구현

12783 단어 딥 러 닝
우선 각종 의존 라 이브 러 리 를 불 러 옵 니 다.인터넷 에서 데 이 터 를 다운로드 해 야 하기 때문에 굵 은 허리 의존 라 이브 러 리 가 많 습 니 다.
import collections
import math
import os
import random
import zipfile
import numpy as np
import urllib
import tensorflow as tf

url lib.request.url retrieve 로 데 이 터 를 다운로드 한 아 소 파일 을 사용 하고 파일 사 이 즈 를 확인 합 니 다.파일 을 다운로드 했다 면 건 너 뜁 니 다.
url='http://mattmahoney.net/dc/'

def maybe_download(filename,expected_bytes):
        if not os.path.exists(filename):
                filename,_=urllib.request.urlretrieve(url+filename,filename)
        statinfo=os.stat(filename)
        if statinfo.st_size==expected_bytes;
                print 'Found and verified',filename
        else:
                print statinfo.st_size
                raise exception('Failed to verify'+filename+',can you get to it with a browser?')
        return filename

filename=maybe_download(text8.zip,31344016)



다음은 다운로드 한 아 소 파일 의 압축 을 풀 고 tf.confat.as 를 사용 합 니 다.str 는 데 이 터 를 단어의 목록 으로 변환 합 니 다.프로그램 출력 을 통 해 데이터 가 마지막 으로 17005207 개의 단 어 를 포함 하 는 목록 으로 바 뀌 었 음 을 알 수 있 습 니 다.
def read_data(filename):
        with zipfile.ZipFile(filename) as f:
                data=tf.compat.as_str(f.read(f.namelist()[0])).split()
        return data

words=read_data(filename)
print 'Data size',len(words)

다음은 vocabulary 어휘 표를 만 드 는 것 입 니 다.우 리 는 collections.Counter 를 사용 하여 단어 목록 의 단어 고용 서 를 통계 한 다음 Most 를 사용 합 니 다.common 방법 은 top 50000 주파수 의 단 어 를 vocabulary 로 하고 dict 를 만 들 며 top 50000 단어의 vocabulary 를 dictionary 에 넣 고 빠 른 검색 을 합 니 다.python 에서 dict 조회 복잡 도 는 o(1)로 성능 이 매우 좋 습 니 다.다음은 모든 단 어 를 번호(주파수 로 정렬 된 번호),top 50000 어휘 이외 의 단어 로 바 꾸 고 우 리 는 이 를 unknown 으로 인정 하여 번 호 를 0 으로 바 꾸 고 이런 단어의 수량 을 통계 한다.다음은 단어 목록 을 옮 겨 다 니 며 각 단어 에 대해 dictionary 에 나타 날 지 여 부 를 판단 하고,그렇지 않 으 면 번호 0(unknown)으로 전환한다.마지막 으로 변 환 된 인 코딩(data),각 단어의 주파수 통계(count),어휘 표(dictionary)와 그 반전 형식(reversedictionary)。
vocabulary_size=50000
def build_dataset(words):
        count=[['UNK',-1]]
        count.extend(collections.Counter(words).most_common(vocabulary_size -1))
        dictionary=dict()
        for word,_ in count:
                dictionary[word]=len(dictionary)
        data=list()
        unk_count=0
        for word in words;
                if word in dictionary:
                        index=dictionary[word]
                else:
                        index=0
                        unk_count+=1
                data.append(index)
        count[0][1]=unk_count
        reverse_dictionary=dict(zip(dictionary.values(),dictionary.keys()))
        return data,count,dictionary,reverse_dictionary

data,count,dictionary,reverse_dictionary = build_dataset(words)

그리고 우 리 는 원본 단어 목록 을 삭제 하면 메모 리 를 해결 할 수 있 습 니 다.vocabulary 에서 가장 높 은 주파수 로 나타 나 는 어휘 와 수량(unknown 어휘 포함)을 인쇄 하면'UNK'와 같은 단 어 는 모두 418391 개 로 볼 수 있 습 니 다.우리 의 data 에서 10 개 단 어 는'anarchism','originated','as','a','term','of','abuse','first','used','against'입 니 다.해당 하 는 번 호 는[5235,3084,12,6,195,2,3137,46,59,156]입 니 다.
del words
print 'Most common words (+UNK)',count[:5]
print 'Sample data',data[:10],[reverse_dictionary[i] for i in data[:10]]

다음은 word2vec 의 훈련 샘플 을 생 성 합 니 다.우리 가 사용 하 는 Skip-Gram 모드(대상 단어 에서 언어 환경 을 반추)는 원본 데이터 인'the quick brown fox jumped over the lazy dog'을(quick,the),(quick,brown),(brown,quick),(brown,fox)등 샘플 로 변환 합 니 다.우리 정의 함수 generatebatch 는 훈련 용 Batch 데 이 터 를 생 성 하 는 데 사용 되 며,매개 변수 중 batchsize 는 batch 크기,skipwindow 는 단어 가 가장 멀리 연결 할 수 있 는 거 리 를 말 하 는데 1 로 설정 하면 가 까 운 두 단어 와 만 샘플 을 생 성 할 수 있 습 니 다.예 를 들 어 quick 은 앞 뒤의 단어 와 만 연 결 된 샘플(quick,the)과(quick,brown)을 생 성 할 수 있 습 니 다.num_skips 는 단어 마다 몇 개의 견본 을 만 들 기 위해 skip 보다 크 면 안 됩 니 다.window 값 의 두 배,그리고 batchsize 는 정수 배 여야 합 니 다.단 어 를 정의 하려 면 data 가 필요 합 니 다.index 는 global 변수 입 니 다.generate 를 반복 적 으로 호출 하기 때 문 입 니 다.batch,그 러 니 data 확보index 함수 generatebatch 에서 수정 되 었 습 니 다.우리 도 assert 로 num 확보skips 와 batchsize 는 앞에서 언급 한 조건 을 만족 시 킵 니 다.그리고 np.ndarray 로 batch 와 labels 를 배열 로 초기 화 합 니 다.여기 서 span 은 특정한 단어 에 대해 관련 견본 을 만 들 때 사용 하 는 단어 수량 으로 목표 단어 자체 와 앞 뒤 단 어 를 포함 하기 때문에 span=2*skipwindow+1.그리고 최대 용량 이 soan 인 deque,즉 양 방향 대기 열 을 만 듭 니 다.deque 에 append 방법 으로 변 수 를 추가 할 때 가장 삽입 할 span 변 수 를 유지 합 니 다.
data_index=0

def generate_batch(batch_size,num_skips,skip_window):
        global data_index
        assert batch_size % num_skips==0
        assert num_skips <=2*skip_window
        batch=np.ndaaray(shape=(batch_size),dtype=np.int32)
        labels=np.ndaaray(shape=(batch_size,1),dtype=np.int32)
        span=2*skip_window+1
        buffer=collection.deque(maxlen=span)
다음은 data 가 필요 합 니 다.index 시작,span 단어 순 서 를 buffer 에 읽 어 초기 값 으로 합 니 다.buffer 는 용량 이 span 인 deque 이기 때문에 이 때 buffer 가 가득 채 워 졌 고 후속 데 이 터 는 앞의 데 이 터 를 교체 합 니 다.그리고 우 리 는 1 층 순환(횟수 는 batchsize/num_skips)목표 단 어 를 순환 할 때마다 샘플 을 생 성 합 니 다.현재 buffer 는 대상 단어 와 모든 관련 단어 입 니 다.target=skip 을 정의 합 니 다.window,즉 buffer 중 제 skipwindow 변 수 는 대상 단어 입 니 다.그리고 샘플 생 성 시 피해 야 할 단 어 를 정의 합 니 다.이 표 targetto_avoid,이 목록 은 처음에 skip 을 포함 합 니 다.window 개 단어(즉 목표 단어)는 우리 가 예측 해 야 할 것 은 언어 환경 단어 이기 때문에 목표 단어 자 체 를 포함 하지 않 습 니 다.다음 2 층 순환 진입(횟수 numskips),매번 순환 중 하나의 언어 환경 단어 에 대해 샘플 을 생 성 합 니 다.먼저 무 작위 수 를 생 성하 고 무 작위 수가 target 에 없 음 을 알 수 있 습 니 다.to_avoid 에서 사용 할 수 있 는 언어 환경 단 어 를 대표 하고 샘플 을 만 듭 니 다.feature 즉,목표 어휘 buffer[skipwindow],label 은 buffer[target]입 니 다.또한,이 언어 환경 단어 가 사용 되 었 기 때문에 target 에 추가 합 니 다.to_avoid 에서 필터 링 합 니 다.대상 단어 에 대한 모든 샘플 생 성 후(numskips 샘플)다음 단 어 를 읽 습 니 다.양쪽 순환 이 완 료 된 후,우 리 는 이미 batch 를 획득 하 였 습 니 다.size 개 훈련 샘플,batch 와 labels 를 함수 결과 로 되 돌려 줍 니 다.
        for _ in range(span):
                buffer.append(data[data_index])
                data_index=(data_index+1)%len(data)
        for i in range(batch_size//num_skips):
                target=skip_window
                target_to_avoid=[skip_window]
                for j in range(num_skips):
                        while target in target_to_avoid:
                                target=random.randint(o,span-1)
                        targets_to_avoid.append(target)
                        batch[i*num_skips+j]=buffer[skip_window]
                        labels[i*num_skips+j,0]=buffer[target]
                buffer.append(data[data_index])
                data_index=(data_index+1)%len(data)
        return batch,labels

여기 서 generate 호출batch 함 수 는 그 기능 을 간단하게 테스트 합 니 다.매개 변수 에서 batchsize 는 8,num 로 설정skips 설정 2,skipwindow 를 1 로 설정 하고 generate 를 실행 합 니 다.batch 및 batch 와 labels 를 획득 합 니 다.batch 와 labels 의 데 이 터 를 다시 인쇄 하면 우리 가 생 성 한 샘플 은'3084 originated->5235 anarchism','3084 originated->12 as','12 as->3084 originated'등 을 볼 수 있 습 니 다.첫 번 째 견본 을 예 로 들 면 3084 는 목표 단어 인 originated 의 번호 이 고 이 단어 에 대응 하 는 언어 환경 단 어 는 anarchism 이 며 그 번 호 는 5235 이다.
batch,labels=generate_batch(batch_size=8,num_skips=2,skip_window=1)
for i in range(8):
        print batch[i],reverse_dictionary[batch[i]],'->',labels[i,0],reverse_dictionary[labels[i,0]]

우리 가 훈련 할 때의 batch 를 정의 합 니 다.size 128,embeddingsize 128,embeddingsize 는 단어 가 조밀 한 벡터 의 차원 으로 바 뀔 것 입 니 다.보통 50-1000 이 범위 내의 값 입 니 다.여 기 는 128 을 단어 벡터 의 차원 으로 사용 합 니 다.skipwindow 는 앞에서 언급 한 단어 사이 에서 가장 멀리 연결 할 수 있 는 거 리 를 1 로 설정 합 니 다.num_skips 는 모든 목표 단어 에서 추출 한 샘플 수 를 2 로 설정 한 다음 에 검증 데이터 valid 를 생 성 합 니 다.examples,여기 서 가장 빈도 가 높 은 단 어 를 무 작위 로 추출 하여 벡터 공간 에서 가장 가 까 운 단어 와 연관 성 이 높 은 지 확인 합 니 다.valid_size=16 추출 에 사용 되 는 검증 단어 수,validwindow=100 은 검증 단 어 를 주파수 가 가장 높 은 100 개 단어 에서 만 추출 하 는 것 을 말 하 며,우 리 는 np.random.choice 함 수 를 사용 하여 무 작위 로 추출 합 니 다.그리고 numsampled 는 훈련 할 때 마이너스 견본 을 만 드 는 소음 단어의 수량 이다.
batch_size=128
embedding_size=128
skip_window=1
num_skips=2

valid_size=16
valid_window=100
valid_examples=np.random.choice(valid_window,valid_size,replace=False)
num_sampled=64
다음은 skip-Gram Word2Vec 모델 의 네트워크 구 조 를 정의 합 니 다.tf.Graph 를 만 들 고 기본 graph 로 설정 합 니 다.그리고 훈련 데이터 에 inputs 와 lebels 의 placeholder 를 만 들 고 앞 에 무 작위 로 생 성 된 validexamples 가 Tensorflow 의 constant 으로 바 뀌 었 습 니 다.그 다음 에 with tf.device('/cpu:0')를 사용 하여 모든 계산 을 CPU 에서 실행 하도록 제한 합 니 다.이 어 진 계산 작업 이 GPU 에서 아직 실현 되 지 않 았 을 수도 있 기 때 문 입 니 다.그리고 tf.random 실현uniform 은 모든 단어의 벡터 embeddings 를 무 작위 로 생 성 합 니 다.단어 표 크기 는 50000 이 고 벡터 차원 은 128 이 며 tf.nn.embedding 을 사용 합 니 다.lookup 찾기 입력 traininputs 에 대응 하 는 벡터 embed.앞서 언급 한 NCE Loss 의 가중치 인자 nce 를 사용 합 니 다.weights,그리고 그 ncebiases 를 0 으로 초기 화 합 니 다.마지막 으로 tf.nn.nce 사용 하기loss 는 단어 벡터 embedding 이 훈련 데이터 에 있 는 Loss 를 계산 하고 tf.reduce 를 참조 합 니 다.평균 집계.
graph=tf.Graph()
with graph.as_default():
        train_inputs=tf.placeholder(tf.int32,shape=[batch_size]) 
        train_labels=tf.placeholder(tf.int32,shape=[batch_size,1])
        valid_dataset=tf.constant(valid_examples,dtype=tf.int32)

        with tf.device('/cpu:0'):
                embeddings=tf.Variable(tf.random_uniform([vocabulary_size,embedding_size],-1.0,1.0))
                embed=tf.nn.embedding_lookup(embeddings,train_inputs)              
                nce_weights=tf.Variable(tf.zeros([vocabulary_size]))
        loss=tf.reduce_mean(tf.nn.nce_loss(weights=nce_weights,biases=nce_biases,labels=train_labels,inputs=embed,num_sampled=num_sampled,num_classes=vocabulary_size))
우 리 는 최적화 기 를 SGD 로 정의 하고 학습 속 도 는 1.0 이다.그리고 벡터 embeddings 에 포 함 된 L2 범 수 norm 를 계산 한 다음 에 embeddings 를 L2 범 수로 나 누 어 표준화 한 normalizedembeddings。tf.nn.embedding 재사 용lookup 은 검 증 된 단어의 삽입 벡터 를 조회 하고 검 증 된 단어의 삽입 벡터 와 어휘 표 의 모든 단어의 유사 성 을 계산 합 니 다.마지막 으로,우 리 는 tf.global 을 사용한다.variables_initializer 모든 모델 매개 변 수 를 초기 화 합 니 다.
    optimizer=tf.train.GradientDescentOptimizer(1.0).minimize(loss)

        norm=tf.sqrt(tf.reduce_sum(tf.square(embeddings),1,keep_dims=True))
        normalized_embeddings=embeddings/norm
        valid_embeddings=tf.nn.embedding_lookup(normalized_embeddings,valid_dataset)
        similarity=tf.matmul(valid_embeddings,normalized_embeddings,transpose_b=True)

        init=tf.global_variables_initializer()

저 희 는 최대 교체 횟수 를 10 만 번 으로 정의 한 다음 에 기본 session 을 만 들 고 설정 하 며 매개 변 수 를 초기 화 합 니 다.모든 훈련 교체 중 generate 사용batch 는 batch 의 inputs 와 labels 데 이 터 를 만 들 고 feed 를 만 듭 니 다.dict。그리고 session.run()을 사용 하여 최적화 기 연산(즉,매개 변수 업데이트)과 계산 을 실행 하고 이 훈련 의 loss 를 average 에 누적 합 니 다.loss。
num_steps=100001 

with tf.Session(graph=graph) as session:
        init.run()
        print "Initialized"

        average_loss=0
        for step in range(num_steps):
                batch_inputs,batch_labels=generate_batch(batch_size,num_skips,skip_window)
                feed_dict={train_inputs:batch_inputs,train_labels:batch_labels}
                _,loss_val=session.run([optimizer,loss],feed_dict=feed_dict)
                average_loss+=loss_val

이후 2000 회 순환 할 때마다 평균 loss 를 계산 해 보 여 준다.
4.567913.10000 번 순환 할 때마다 검 증 된 단어 와 모든 단어의 싱크로 율 을 계산 하고 검 증 된 단어 와 가장 비슷 한 8 개의 단 어 를 보 여 줍 니 다.
           if step % 2000==0:
                        if step>0:
                                average_loss/=2000
                        print 'Average loss at step',step,':',average_loss
                        average_loss=0

==================================================================================================================여기 lowdim_embs 는 2 차원 으로 내 려 가 는 단어의 공간 벡터 로 아이콘 에 모든 단어의 위 치 를 보 여 줍 니 다.우 리 는 plt.scatter(일반적으로 matplotlib.pyplot 이름 은 plt)를 사용 하여 산 점도(단어의 위치)를 표시 하고 plt.annotate 로 단어 자 체 를 보 여 줍 니 다.동시에 plt.savefig 를 사용 하여 로 컬 파일 에 그림 을 저장 합 니 다.
4.567913.우 리 는 sklearn.manifold.TSNE 를 사용 하여 강 위 를 실현 합 니 다.여 기 는 원시 적 인 128 차원 의 끼 워 넣 는 벡터 를 2 차원 으로 낮 추고 앞의 plot 를 사용 합 니 다.with_labels 함수 전시.주파수 가 가장 높 은 100 개의 단어의 시각 화 결과 만 표시 합 니 다.
            if step % 10000==0:
                        sim=similarity.eval()
                        for i in range(valid_size):     
                                valid_word=reverse_dictionary[valid_examples[i]]
                                top_k=8
                                nearest=(-sim[i,:]).argsort()[1:top_k+1]
                                log_str='Nearest to %s:' % valid_word
                                for k in range(top_k):
                                        close_word=reverse_dictionary[nearest[k]]
                                        log_str='%s %s,' % (log_str,close_word)
                                print log_str
        final_embeddings=normalized_embeddings.eval()

좋은 웹페이지 즐겨찾기