0부터 단어 연상 네트워크 구축
21161 단어 machinelearningpythonspacynlp
이 기능의 구현을 계획하기 시작했을 때 첫 번째 생각은 다음과 같습니다.
이것은 너무 어렵지 않아야 한다. 나는 단지 다음과 같이 생각했다.
그러나 내가 나의 소망을 코드로 바꾸기 시작했을 때, 나는 기술적 제한에 부딪혔다.
우선, 나는 검색 속도가 매우 빠르기를 원하기 때문에, 실시간으로 여현의 싱크로율을 계산하는 것은 불가능하다. 그것은 너무 오래 걸릴 뿐이다.
또한 계산 시간을 <50ms로 최적화할 수 있어도
en_core_web_md
모델 자체가 200MB를 초과할 때 spacy모델을 웹에 어떻게 배치합니까?나는 꼬박 3일이 걸려서야 실행 가능한 해결 방안을 생각해냈다. 이것이 바로 내가 이 블로그가 네가 더욱 짧은 시간 안에 이 점을 할 수 있도록 도와줄 수 있기를 바라는 이유이다.
어휘 연상 네트워크를 구축하다.
일련의 연구를 한 후에 나는 검색 시간을 50밀리초 이하로 줄일 수 있는 방법이 하나밖에 없다는 결론을 얻었다. 즉, 로컬 사전 훈련 모델에서 결과를 PostgreSQL에 저장할 수 있다는 것이다.
기본적으로 내가 해야 할 일은 현재 데이터베이스에 있는 2만 개의 단어 간의 관계를 비추는 단어 관련 네트워크를 구축하는 것이다.
상상해 보세요.
참고: 각 모서리의 십진수 값은 보조 항목과 루트 사이의 유사성 분수를 나타냅니다.
지금 다시 상상해 보세요. 하지만 이번에는 20000개의 형용사, 명사, 동사와 10개의 다른 종류+프랑스어와 스페인어 단어*가 있습니다.
알아요. 미치고 멋있게 들리죠?
먼저 가상 환경에 spacy 라이브러리를 설치하고 en_core_web_md
모델을 다운로드했습니다.
pip install spacy
python3 -m spacy download en_core_web_md
그런 다음 Flask 응용 프로그램을 가져와 단어 벡터를 로드합니다.
import spacy
import en_core_web_md
nlp = en_core_web_md.load()
지금은 단어 관련 모델을 구축할 때다.나는 먼저 One Word Domains의 음성 목록을 가져와 그것들을 표시했다.그리고 플러그인 for 순환을 사용하여 나는 단어 사이의 여현 유사성을 계산했고 addToList
함수를 사용하여 단어마다 100개의 가장 비슷한 보조어 목록을 보존하고 모든 내용을 사전에 저장했다.이러한 모든 코드는 다음과 같습니다.
# Add to list function to add the list of significant scores to list
def addToList(ele, lst, num_ele):
if ele in lst:
return lst
if len(lst) >= num_ele: #if list is at capacity
if ele[1] > float(lst[-1][1]): #if element's sig_score is larger than smallest sig_score in list
lst.pop(-1)
lst.append((ele[0], str(ele[1])))
lst.sort(key = lambda x: float(x[1]), reverse=True)
else:
lst.append((ele[0], str(ele[1])))
lst.sort(key = lambda x: float(x[1]), reverse=True)
return lst
import json
# list of English vocabs
en_vocab = ['4k', 'a', 'aa', ...]
# tokenizing the words in the vocab list
tokens = nlp(' '.join(en_vocab))
# initiate empty dictionary to store the results
en_dict = {}
# Nested for loop to calculate cosine similarity scores
for i in range(len(en_vocab)):
word = en_vocab[i]
print('Processing for '+ word + ' ('+ str(i) + ' out of '+ str(len(en_vocab)) + ' words)')
for j in range(i+1, len(en_vocab)):
prev_list_i = en_dict[str(tokens[i])]['similar_words']
en_dict[str(tokens[i])]['similar_words'] = addToList((str(tokens[j]), tokens[i].similarity(tokens[j])), prev_list_i, 100)
prev_list_j = en_dict[str(tokens[j])]['similar_words']
en_dict[str(tokens[j])]['similar_words'] = addToList((str(tokens[i]), tokens[i].similarity(tokens[j])), prev_list_j, 100)
with open('data.json', 'w') as f:
json.dump(en_dict, f)
이 코드는 운행하는 데 아주 오랜 시간이 걸렸다.20000개의 단어에 대해 모두 2000010000개의 조합(200000+19999+19998+...+3+2+1=20001*10000=200010000000)이 있다.모든 조합이 약 반 밀리초의 시간이 걸려야 완성할 수 있다는 것을 감안하면 전체 과정이 약 36시간이 걸려야 완성할 때 이상하지 않다.
그러나 36시간의 힘든 작업이 끝난 후에 나는 단어 목록을 하나 만들었는데 단어마다 가장 비슷한 단어가 100개씩 있었다.
데이터 검색 속도를 높이기 위해 저는 PostgreSQL에 데이터를 저장하기 시작했습니다. 이것은 믿을 수 없는 확장성과 강력한 기능을 가진 관계 데이터베이스입니다. 특히 대량의 데이터가 관련될 때입니다.나는 다음 코드 행을 통해 이 점을 실현했다.
def store_db_postgres():
with open('data.json', 'r') as f:
data = json.load(f)
for word in data.keys():
db_cursor.execute("""INSERT INTO dbname (word, param) VALUES (%s, %s);""", (word, json.dumps(data[word]['similarity'])))
db_conn.commit()
return 'OK', 200
봐라!현재, 당신은 최소한의 지연 상태에서 단어 관련 네트워크의 수백만 개의 가장자리를 통과할 수 있다. (내가 지난번에 검사했을 때, 그것은 50밀리초 이하의 수준에 있었다.)이 검색 도구는 현재 One Word Domains에 위치하고 있으며 마음대로 사용할 수 있습니다.
*프랑스어와 스페인어 단어는 각각 fr_core_news_md
과 es_core_news_md
모형에서 훈련한다.
클라우드에 배포
까다로운 부분이 왔다.내 단어 관련 네트워크에는 가장 자주 사용하는 영어 단어가 2만 개가 넘지만 사용자의 조회는 내 지식 라이브러리에 속하지 않을 가능성이 있다는 것을 나는 안다.
따라서 실행 중 결과를 생성할 수 있도록 사용자에게 옵션을 추가하고 싶습니다.이를 위해 스페이스 모델을 웹에 업로드해야 단어 관련 네트워크에 실시간으로 추가 테두리를 구축할 수 있습니다.
그러나 이것은 Heroku에서 불가능하다. 왜냐하면 500MB의 피스톤 크기가 딱딱하기 때문이다. (나의 현재 피스톤 크기는 이미 300MB이다.)더 강력한 대안이 필요해서 AWS Lambda를 선택하기로 했습니다.
내가 처음으로 Lambda 함수s를 만났을 때, 나는 그것들을 사용하여 movie chatbot의 NLP 구성 요소를 위탁 관리해야 했다. 이것은 내가 올해 가을에 나의 AI류를 위해 구축한 것이다.
Lambda 함수는 처음에는 상당히 복잡하게 설정되었지만 편리한 Zappa library과 대량의 Stack Overflow 게시물의 도움으로 주어진 조회에 가장 비슷한 단어를 찾아 JSON 형식으로 되돌려주는 단어역 자체의 Lambda 함수를 구축할 수 있습니다.
나는 배치 과정에 대해 깊이 토론하지 않겠지만, 이것은 guide으로 나에게 매우 큰 도움을 주었다.또한 지정된 질의에 가장 밀접한 연관이 있는 100개의 단어를 찾을 수 있는 주요 구동 함수도 있습니다.
@app.route('/generate')
@cross_origin()
def generate_results():
# get vocab
vocab_pickle = s3.get_object(Bucket='intellisearch-assets', Key='vocab')['Body'].read()
vocab_only = pickle.loads(vocab_pickle)
vocab_only = list(set(vocab_only))
# add new query to vocab
vocab_only.insert(0, query)
# store vocab back to pickle
serialized_vocab = pickle.dumps(vocab_only)
s3.put_object(Bucket='intellisearch-assets', Key='vocab', Body = serialized_vocab)
# do the rest
tokens = nlp(' '.join(vocab_only))
results = []
for i in range(1, len(vocab_only)):
if str(tokens[i]) != query:
results.append([str(tokens[i]), tokens[0].similarity(tokens[i])])
results.sort(key=lambda x: x[1], reverse=True)
return results[:100]
여기에서, 나는pickle 파일 형식으로vocab 목록을AWS S3에 저장합니다. 새로운 검색이 있을 때마다, 나는 s3.get_obect
검색 목록을 사용하고, 새로운 단어를 목록에 삽입해서 업데이트합니다.Flask의 CORS 라이브러리에 있는 @cross_origin()
장식기를 사용하고 있습니다. 왜냐하면 Heroku 프로그램에서 이 Lambda 함수를 호출할 것입니다.
그게 바로...별로 차이 안 나죠?내가 지금 해야 할 일은 AWS Lambda API 포트를 최초의 Heroku 응용 프로그램에 연결해서 사용자가 사이트에 입력한 주어진 검색 조회에 관련 단어의 목록을 만드는 데 도움을 주는 것이다.다음은 이 방면의 대강이다.
import requests
url = "https://my-api-endpoint.amazonaws.com/generate?query=" + query
response = requests.get(url)
similar_words = response.json()
print(similar_words)
마지막으로 중요한 순간입니다. 여기는 Loom recording이 있는데, 실시간 검색이 한 단어에서 어떻게 작동하는지 보여 줍니다.
이것은 기능이 완비된 검색 알고리즘으로 20000개의 노드와 수백만 개의 변을 포함하는 단어 관련 네트워크 위에 세워졌다.
페이지 맨 위에 있는 One Word Domains의 검색 도구를 마음대로 사용하십시오.만약 피드백이 있거나 버그를 발견하면 언제든지 채팅을 통해 저에게 메시지를 보내주세요. contact page, email 또는 - 기꺼이 도움을 드리겠습니다!
Reference
이 문제에 관하여(0부터 단어 연상 네트워크 구축), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://dev.to/steventey/building-a-word-association-network-from-scratch-1j7e
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
pip install spacy
python3 -m spacy download en_core_web_md
import spacy
import en_core_web_md
nlp = en_core_web_md.load()
# Add to list function to add the list of significant scores to list
def addToList(ele, lst, num_ele):
if ele in lst:
return lst
if len(lst) >= num_ele: #if list is at capacity
if ele[1] > float(lst[-1][1]): #if element's sig_score is larger than smallest sig_score in list
lst.pop(-1)
lst.append((ele[0], str(ele[1])))
lst.sort(key = lambda x: float(x[1]), reverse=True)
else:
lst.append((ele[0], str(ele[1])))
lst.sort(key = lambda x: float(x[1]), reverse=True)
return lst
import json
# list of English vocabs
en_vocab = ['4k', 'a', 'aa', ...]
# tokenizing the words in the vocab list
tokens = nlp(' '.join(en_vocab))
# initiate empty dictionary to store the results
en_dict = {}
# Nested for loop to calculate cosine similarity scores
for i in range(len(en_vocab)):
word = en_vocab[i]
print('Processing for '+ word + ' ('+ str(i) + ' out of '+ str(len(en_vocab)) + ' words)')
for j in range(i+1, len(en_vocab)):
prev_list_i = en_dict[str(tokens[i])]['similar_words']
en_dict[str(tokens[i])]['similar_words'] = addToList((str(tokens[j]), tokens[i].similarity(tokens[j])), prev_list_i, 100)
prev_list_j = en_dict[str(tokens[j])]['similar_words']
en_dict[str(tokens[j])]['similar_words'] = addToList((str(tokens[i]), tokens[i].similarity(tokens[j])), prev_list_j, 100)
with open('data.json', 'w') as f:
json.dump(en_dict, f)
def store_db_postgres():
with open('data.json', 'r') as f:
data = json.load(f)
for word in data.keys():
db_cursor.execute("""INSERT INTO dbname (word, param) VALUES (%s, %s);""", (word, json.dumps(data[word]['similarity'])))
db_conn.commit()
return 'OK', 200
까다로운 부분이 왔다.내 단어 관련 네트워크에는 가장 자주 사용하는 영어 단어가 2만 개가 넘지만 사용자의 조회는 내 지식 라이브러리에 속하지 않을 가능성이 있다는 것을 나는 안다.
따라서 실행 중 결과를 생성할 수 있도록 사용자에게 옵션을 추가하고 싶습니다.이를 위해 스페이스 모델을 웹에 업로드해야 단어 관련 네트워크에 실시간으로 추가 테두리를 구축할 수 있습니다.
그러나 이것은 Heroku에서 불가능하다. 왜냐하면 500MB의 피스톤 크기가 딱딱하기 때문이다. (나의 현재 피스톤 크기는 이미 300MB이다.)더 강력한 대안이 필요해서 AWS Lambda를 선택하기로 했습니다.
내가 처음으로 Lambda 함수s를 만났을 때, 나는 그것들을 사용하여 movie chatbot의 NLP 구성 요소를 위탁 관리해야 했다. 이것은 내가 올해 가을에 나의 AI류를 위해 구축한 것이다.
Lambda 함수는 처음에는 상당히 복잡하게 설정되었지만 편리한 Zappa library과 대량의 Stack Overflow 게시물의 도움으로 주어진 조회에 가장 비슷한 단어를 찾아 JSON 형식으로 되돌려주는 단어역 자체의 Lambda 함수를 구축할 수 있습니다.
나는 배치 과정에 대해 깊이 토론하지 않겠지만, 이것은 guide으로 나에게 매우 큰 도움을 주었다.또한 지정된 질의에 가장 밀접한 연관이 있는 100개의 단어를 찾을 수 있는 주요 구동 함수도 있습니다.
@app.route('/generate')
@cross_origin()
def generate_results():
# get vocab
vocab_pickle = s3.get_object(Bucket='intellisearch-assets', Key='vocab')['Body'].read()
vocab_only = pickle.loads(vocab_pickle)
vocab_only = list(set(vocab_only))
# add new query to vocab
vocab_only.insert(0, query)
# store vocab back to pickle
serialized_vocab = pickle.dumps(vocab_only)
s3.put_object(Bucket='intellisearch-assets', Key='vocab', Body = serialized_vocab)
# do the rest
tokens = nlp(' '.join(vocab_only))
results = []
for i in range(1, len(vocab_only)):
if str(tokens[i]) != query:
results.append([str(tokens[i]), tokens[0].similarity(tokens[i])])
results.sort(key=lambda x: x[1], reverse=True)
return results[:100]
여기에서, 나는pickle 파일 형식으로vocab 목록을AWS S3에 저장합니다. 새로운 검색이 있을 때마다, 나는 s3.get_obect
검색 목록을 사용하고, 새로운 단어를 목록에 삽입해서 업데이트합니다.Flask의 CORS 라이브러리에 있는 @cross_origin()
장식기를 사용하고 있습니다. 왜냐하면 Heroku 프로그램에서 이 Lambda 함수를 호출할 것입니다.그게 바로...별로 차이 안 나죠?내가 지금 해야 할 일은 AWS Lambda API 포트를 최초의 Heroku 응용 프로그램에 연결해서 사용자가 사이트에 입력한 주어진 검색 조회에 관련 단어의 목록을 만드는 데 도움을 주는 것이다.다음은 이 방면의 대강이다.
import requests
url = "https://my-api-endpoint.amazonaws.com/generate?query=" + query
response = requests.get(url)
similar_words = response.json()
print(similar_words)
마지막으로 중요한 순간입니다. 여기는 Loom recording이 있는데, 실시간 검색이 한 단어에서 어떻게 작동하는지 보여 줍니다.이것은 기능이 완비된 검색 알고리즘으로 20000개의 노드와 수백만 개의 변을 포함하는 단어 관련 네트워크 위에 세워졌다.
페이지 맨 위에 있는 One Word Domains의 검색 도구를 마음대로 사용하십시오.만약 피드백이 있거나 버그를 발견하면 언제든지 채팅을 통해 저에게 메시지를 보내주세요. contact page, email 또는 - 기꺼이 도움을 드리겠습니다!
Reference
이 문제에 관하여(0부터 단어 연상 네트워크 구축), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/steventey/building-a-word-association-network-from-scratch-1j7e텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)