250x250
Notice
Recent Posts
Recent Comments
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
Tags
- r
- 토픽추출
- tomoto
- spring MVC(모델2)방식
- 이력서
- 방식으로 텍스트
- 과학백과사전
- 지마켓
- Websocket
- 게시판 만들기
- test
- pytorch
- Python
- Gmarket
- Topics
- db
- (깃)git bash
- 크롤링
- word2vec
- mysql
- jsp 파일 설정
- 파이썬
- 코사인 유사도
- java
- 네이버뉴스
- 자바
- RESFUL
- 幼稚园杀手(유치원킬러)
- oracle
- lda
Archives
- Today
- Total
무회blog
0003-scikit-lear,방식으로 텍스트 ,코사인 유사도, 구하기-004-01 본문
0003-scikit-lear,방식으로 텍스트 ,코사인 유사도, 구하기-004¶
scikit-learn 001 방식 체크¶
In [1]:
from sklearn.metrics.pairwise import cosine_similarity
a=[[1,3,2],[2,2,1]]
cosine_similarity(a) # 余弦相似度
Out[1]:
In [2]:
from sklearn.metrics.pairwise import pairwise_distances
pairwise_distances(a,metric="cosine") # 注意该方法返回的是余弦距离
Out[2]:
In [3]:
from numpy import dot
from numpy.linalg import norm
import numpy as np
def cos_sim(A, B):
return dot(A, B)/(norm(A)*norm(B))
# doc1 = np.array(['바나나','사과','키위'])
# doc2 = np.array(['바나나','사과','딸기'])
doc1=np.array([0,1,1,1])
doc2=np.array([0,0,2,1])
print(cos_sim(doc1,doc2))
In [4]:
# 엑셀 vlookup 방식으로 title 과 content 내용을 출력 하기
import pandas as pd
data = pd.read_excel('./../test_data/test_Newsdata-100.xlsx')
data = data[['subMenu','title','content','yoyag']]
data['content'].isnull().sum() # 널값이 몇개있는지 체크
# data['overview'] = data['overview'].fillna('') # overview에서 Null 값을 가진 경우에는 값 제거
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(stop_words='english')
tfidf_matrix = tfidf.fit_transform(data['content']) # #第一个fit_transform是计算tf-idf,# 第二个fit_transform是将文本转为词频矩阵
# content 대해서 tf-idf 수행
print(tfidf_matrix.shape) # (100, 12038) -> 100 행을표현하기 위하여 , 12038 개의 단어를 사용
from sklearn.metrics.pairwise import linear_kernel ,cosine_similarity
cosine_sim = linear_kernel(tfidf_matrix, tfidf_matrix) # 코사인 유사도를 구합니다.
print(type(cosine_sim))
# print(cosine_sim[99]) # 100 개 문서에 대한 코사인 유사도
print(len(cosine_sim))
print(cosine_sim)
# scosine_similarity =cosine_similarity(tfidf_matrix,tfidf_matrix)
# print(type(scosine_similarity))
# print(scosine_similarity)
In [5]:
indices = pd.Series(data.index, index=data['title']).drop_duplicates()
print(indices.head())
# target_title = '6ㆍ25 70주년 애국가 ‘아무리 봐도 북한 애국가’ 논란 '
target_title = '남한 기대 수명 83세 세계 9위, 북한은 얼마일까 '
target_title = target_title.strip()
idx = indices[target_title]
print(idx)
def get_recommendations(title, cosine_sim=cosine_sim):
# 선택한 타이틀로부터 해당되는 인덱스를 받아옵니다. 이제 선택한 것 가지고 연산할 수 있습니다.
idx = indices[title]
# 모든 타이틀 대해서 해당 타이틀 유사도를 구합니다.
sim_scores = list(enumerate(cosine_sim[idx]))
# 유사도에 따라 타이틀들을 정렬합니다.
sim_scores = sorted(sim_scores, key=lambda x: x[1], reverse=True)
# 가장 유사한 10개의 타이틀를 받아옵니다.
sim_scores = sim_scores[1:11]
# 가장 유사한 10개의 타이틀의 인덱스를 받아옵니다.
title_indices = [i[0] for i in sim_scores]
# 가장 유사한 10개의 타이틀의 제목을 리턴합니다.
return data['content'].iloc[title_indices]
print('target_title : ',target_title)
get_recommendations(target_title)
Out[5]:
scikit-learn 002 방식 체크¶
In [6]:
import pandas as pd
pd.options.mode.chained_assignment = None
import numpy as np
np.random.seed(0) # 랜덤 난수를 지정하여 사용
# test = np.random.permutation(10)
# print(test)
from konlpy.tag import Twitter
twitter = Twitter()
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer, HashingVectorizer
from sklearn.metrics.pairwise import linear_kernel, cosine_similarity
In [7]:
# tokenizer : 문장에서 색인어 추출을 위해 명사,동사,알파벳,숫자 정도의 단어만 뽑아서 normalization, stemming 처리하도록 함
def tokenizer(raw, pos=["Noun","Alpha","Verb","Number"], stopword=[]):
return [
word for word, tag in twitter.pos(
raw,
norm=True, # normalize 그랰ㅋㅋ -> 그래ㅋㅋ
stem=True # stemming 바뀌나->바뀌다
)
if len(word) > 1 and tag in pos and word not in stopword
]
# 테스트 문장
rawdata = [
'남북 고위급회담 대표단 확정..남북 해빙모드 급물살',
'[남북 고위급 회담]장차관만 6명..판 커지는 올림픽 회담',
'문재인 대통령과 대통령의 영부인 김정숙여사 내외의 동반 1987 관람 후 인터뷰',
'1987 본 문 대통령.."그런다고 바뀌나? 함께 하면 바뀐다"',
'이명박 전 대통령과 전 대통령의 부인 김윤옥 여사, 그리고 전 대통령의 아들 이시형씨의 동반 검찰출석이 기대됨'
]
rawdata
Out[7]:
In [8]:
# 문서목록에서 각 문서의 feature(문장의 특징) 노출수를 가중치로 설정한 BOW 벡터를 만든다.
vectorize = CountVectorizer(
tokenizer=tokenizer,
min_df=2 # 예제로 보기 좋게 1번 정도만 노출되는 단어들은 무시하기로 했다
# min_df = 0.01 : 문서의 1% 미만으로 나타나는 단어 무시
# min_df = 10 : 문서에 10개 미만으로 나타나는 단어 무시
# max_df = 0.80 : 문서의 80% 이상에 나타나는 단어 무시
# max_df = 10 : 10개 이상의 문서에 나타나는 단어 무시
)
# 문장에서 노출되는 feature(특징이 될만한 단어) 수를 합한 Document Term Matrix(이하 DTM) 을 리턴한다
X = vectorize.fit_transform(rawdata) # 인덱스 , tf-idf 기준의 DTM 값을 리턴한다.
print(
'fit_transform, (sentence {}, feature {})'.format(X.shape[0], X.shape[1])
)
dtm_bindo = X.toarray() # 5 행 7 열 에 대한 피쳐
features = vectorize.get_feature_names() # ['1987', '고위', '남북', '대통령', '동반', '여사', '회담']
print(features)
[print(x) for x in rawdata]
df_ = pd.DataFrame(dtm_bindo, columns=features) # feature or topic 기준 , DTM 테이블 구성하기
df_
Out[8]:
In [9]:
# 검색 문장에서 feature를 뽑아냄
input_text = '1987 관람한 대통령 인터뷰 기사'
srch=[t for t in tokenizer(input_text) if t in features]
print(srch) # ['1987', '대통령']
# dtm 에서 검색하고자 하는 feature만 뽑아낸다.
srch_dtm = np.asarray(X.toarray())[:, [
# vectorize.vocabulary_.get 는 특정 feature 가 dtm 에서 가지고 있는 컬럼의 인덱스값 을 리턴한다
vectorize.vocabulary_.get(i) for i in srch
]]
In [10]:
score = srch_dtm.sum(axis=1)
print(score)
# array([0, 0, 3, 2, 3], dtype=int64) 문장별 feature 합계 점수
for i in score.argsort()[::-1]: # argsort-큰값부터 순서대로 데이터의 위치를 반환
if score[i] > 0: # score[i] 는 feature 합계의 인덱스 , i 는 디센딩으로 들어오는 스코어 인덱스
print('{} 번째 문장에 디센딩 순서문장은: , {} / score : {}'.format(i, rawdata[i], score[i]))
# # 이명박 전 대통령과 전 대통령의 부인 김윤옥 여사, 그리고 전 대통령의 아들 이시형씨의 동반 검찰출석이 기대됨 / score : 3
# # 문재인 대통령과 대통령의 영부인 김정숙여사 내외의 동반 1987 관람 후 인터뷰 / score : 3
# # 1987 본 문 대통령.."그런다고 바뀌나? 함께 하면 바뀐다" / score : 2
In [11]:
## TfidfVectorizer 방식으로 가중치를 주어서 Bow 를 만들다
vectorize = TfidfVectorizer(
tokenizer=tokenizer,
min_df=2,
sublinear_tf=True # tf값에 1+log(tf)를 적용하여 tf값이 무한정 커지는 것을 막음
)
X = vectorize.fit_transform(rawdata)
print(
'fit_transform, (sentence {}, feature {})'.format(X.shape[0], X.shape[1])
)
# fit_transform, (sentence 5, feature 7)
print(X.toarray())
# ([[0. , 0.40824829, 0.81649658, 0. , 0. , 0. , 0.40824829],
# [0. , 0.40824829, 0.40824829, 0. , 0. , 0. , 0.81649658],
# [0.41680418, 0. , 0. , 0.69197025, 0.41680418, 0.41680418, 0. ],
# [0.76944707, 0. , 0. , 0.63871058, 0. , 0. , 0. ],
# [0. , 0. , 0. , 0.8695635 , 0.34918428, 0.34918428, 0. ]])
# 문장에서 뽑아낸 feature 들의 배열
features = vectorize.get_feature_names()
print(features)
df_tfi = pd.DataFrame(X.toarray(), columns=features)
df_tfi
Out[11]:
In [12]:
# 검색 문장에서 feature를 뽑아냄
srch=[t for t in tokenizer('1987 관람한 대통령 인터뷰 기사') if t in features]
print(srch)
# ['1987', '대통령']
# dtm 에서 검색하고자 하는 feature만 뽑아낸다.
srch_dtm = np.asarray(X.toarray())[:, [
# vectorize.vocabulary_.get 는 특정 feature 가 dtm 에서 가지고 있는 index값을 리턴한다
vectorize.vocabulary_.get(i) for i in srch
]]
# 1987 대통령
# 0 0.000000 0.000000
# 1 0.000000 0.000000
# 2 0.416804 0.691970
# 3 0.769447 0.638711
# 4 0.000000 0.869563
score = srch_dtm.sum(axis=1)
print(score)
# array([0. 0. 1.10877443 1.40815765 0.8695635 ], dtype=int64) 문장별 feature 합계 점수
for i in score.argsort()[::-1]:
if score[i] > 0:
print('{} / score : {}'.format(rawdata[i], score[i]))
# 1987 본 문 대통령.."그런다고 바뀌나? 함께 하면 바뀐다" / score : 1.408157650537996
# 문재인 대통령과 대통령의 영부인 김정숙여사 내외의 동반 1987 관람 후 인터뷰 / score : 1.1087744279177436
# 이명박 전 대통령과 전 대통령의 부인 김윤옥 여사, 그리고 전 대통령의 아들 이시형씨의 동반 검찰출석이 기대됨 / score : 0.869563495264799
In [13]:
## HashingVectorizer 방식으로 테스트 해보기 ,
## 대용량 텍스트를 벡터화 할때 많이 쓰인다, CountVectorizer, TfidfVectorizer 와 달리 벡터화 할때 모든 feature 에 대해 사전을 만들지 않고, 해싱함수를 통해 벡터안의 인덱스를 특정하도록 한다. 큰 사전을 만들 필요가 없어 메모리 소모가 적어 대용량 텍스트를 벡터화 할때 많이 쓰인다.
vectorize = HashingVectorizer(
tokenizer=tokenizer,
n_features=7 # 기본 feature 수를 설정하며 기본값이 2의 20승이다. 아래 예시를 위해 feature 를 7로 한정했으나, 아래 유사문장을 찾을때는 다시 n_features 주석처리 했다.
)
X = vectorize.fit_transform(rawdata)
print(X.shape)
# (5, 7)
print(X.toarray())
# ([[ 0.33333333, 0.33333333, -0.33333333, 0.33333333, 0.33333333, 0.66666667, 0. ],
# [ 0. , 0. , -0.57735027, 0.57735027, 0.57735027, 0. , 0. ],
# [ 0. , 0. , 0. , 0. , -0.21821789, -0.43643578, 0.87287156],
# [ 0. , 0. , 0. , 0.81649658, 0. , -0.40824829, 0.40824829],
# [ 0.28867513, 0.28867513, -0.28867513, 0.28867513, -0.57735027, 0. , 0.57735027]])
In [14]:
# search 문장 벡터
srch_vector = vectorize.transform([
'1987 관람한 대통령 인터뷰 기사'
])
print(srch_vector.shape)
# (1, 7)
In [15]:
from sklearn.metrics.pairwise import linear_kernel
# linear_kernel는 두 벡터의 dot product 이다.
cosine_similar = linear_kernel(srch_vector, X).flatten()
# cosine_similar = (srch_vector*X.T).toarray().flatten()
print(cosine_similar)
# [0. 0. 0.62017367 0.31622777 0.3]
print(cosine_similar.shape)
# (5,)
# 유사한 rawdata index
sim_rank_idx = cosine_similar.argsort()[::-1]
print(sim_rank_idx)
#[2 3 4 1 0]
for i in sim_rank_idx:
if cosine_similar[i] > 0:
print('{} / score : {}'.format(rawdata[i], cosine_similar[i]))
# 문재인 대통령과 대통령의 영부인 김정숙여사 내외의 동반 1987 관람 후 인터뷰 / score : 0.6201736729460423
# 1987 본 문 대통령.."그런다고 바뀌나? 함께 하면 바뀐다" / score : 0.3162277660168379
# 이명박 전 대통령과 전 대통령의 부인 김윤옥 여사, 그리고 전 대통령의 아들 이시형씨의 동반 검찰출석이 기대됨 / score : 0.3
In [16]:
# # a = [1, 2, 3, 4, 5] # a list
# # a = np.asarray(a)
# # a
# test1 = np.asarray(X.toarray())
# test = np.asarray(X.toarray())[:, [
# vectorize.vocabulary_.get('1987')
# ]]
# # test = vectorize.vocabulary_.get('1987')
# print(test1)
# print(test)
# # print(test1[:,[0]])
# print(srch_dtm)
# score = srch_dtm.sum(axis=0) # 내리방향으로 더하기
# score = srch_dtm.sum(axis=1) # 가로 방향으로 더하기
# print(score)
# print(score.argsort()[::]) # argsort-작은값부터 순서대로 데이터의 위치를 반환
# print(score.argsort()[::-1]) # argsort-큰값부터 순서대로 데이터의 위치를 반환
'Python' 카테고리의 다른 글
clustering,-test00-군집분류,및 분류예측기,-001 (0) | 2020.07.20 |
---|---|
0003-scikit-learn,방식 004-003, 사이킷런 문서유사도, 3가지 방식 (0) | 2020.07.15 |
1차 텍스트유사도 3가지 , word2vec,doc2vec,LSI방식, 등 , 성공 src (0) | 2020.07.14 |
python: 200713-텍스트유사도, 문서유사도, 방식, 3가지 LSI,word2vec,doc2Vec ,SrcFile (0) | 2020.07.13 |
0003-Doc2vec ,방식으로 텍스트 ,코사인 유사도, 구하기-003-02 (0) | 2020.07.13 |
Comments