wordvec 자연어처리후 학습 한 것을 외부 데이터를 읽어내 확률 추출해 내는것이 궁금합니다.

조회수 567회

현재 id/date/text/smishing 행을 가진 데이터에서 text/smishing만 추출해 word2vec로 자연어처리후 랜덤포레스트와 KNN으로 학습했습니다. 이 학습한 것을 test.csv라는 id/date/text 행만 가진 데이터를 읽어내 스미싱 여부 및 그 확률을 추출해내고자 합니다.

다음 코드는 훈련했던 코드 들입니다.

데이터를 불러와 범위 설정

import numpy as np
import pandas as pd
import konlpy
ham_spam = pd.read_csv(r'C:\Users\chlwn\Desktop\JUNO\data\smishing data\train.csv')
data = list(zip(ham_spam['text'],ham_spam['smishing']))
text = [data[i][0] for i in range(30000)]
label = [data[i][1] for i in range(30000)]

데이터 텍스트 분리 및 train과 test 데이터 분리

import re
text1 = [re.sub('\d+',' ',tmp) for tmp in text]
text2 = [re.sub('\W+',' ',tmp) for tmp in text1]
text_split = [tmp.split(' ') for tmp in text2]
text_split
from sklearn.model_selection import train_test_split
text_train, text_test, label_train, label_test = train_test_split(text_split, label, random_state = 0)
#####text(메일 내용)의 train과 test 를 나눠줌
##### 정답인 label(ham인지 spam인지)도 train, test 따로 나눠줌
###### random_state : 난수 고정 / test_size(default) : 0.25

print(len(text_train), len(text_test))  
print(len(label_train), len(label_test)) 
불용어 처리
stop_words = ['XXX','나','너','아이','오직','때','시각']
def rm_stop(token):
    final = []
    for words in token:
        word_list = []
        for word in words:
            if word.split("/")[0] not in stop_words:
                word_list.append(word)
        final.append(word_list)
    return final
text_train = rm_stop(text_train)
text_test = rm_stop(text_test)
from gensim.models import Word2Vec
##### Skip-gram (sg=1)
w2v_skip_gram = Word2Vec(text_train, size=100, window=10, min_count=10, workers=4, sg=1)
##### CBOW (sg=0)
w2v_CBOW = Word2Vec(text_train, size=100, window=10, min_count=10, workers=4, sg=0)
### Text embedding 하기
from sklearn.feature_extraction.text import TfidfVectorizer
from collections import defaultdict
import numpy as np

문서 embedding

class TfidfEmbeddingVectorizer(object):
    def __init__(self, word2vec):
        self.word2vec = word2vec

    def transform(self, X):
        tfidf = TfidfVectorizer(analyzer = lambda x : x) 
        tfidf.fit(X)
        max_idf = max(tfidf.idf_) 
        word2weight = defaultdict(lambda : max_idf, [(w, tfidf.idf_[i]) for w, i in tfidf.vocabulary_.items()]) 

        array_list =[]
        for words in X:
            array_list.append(np.array(np.mean([self.word2vec[w]*word2weight[w] for w in words if w in self.word2vec] or [np.zeros(100)], axis = 0)))
        return(array_list)

vec_tf_skip_gram = TfidfEmbeddingVectorizer(w2v_skip_gram)
vec_tf_CBOW = TfidfEmbeddingVectorizer(w2v_CBOW)

Word2vec을 이용 단어들간의 관계 설정으로 smishing여부 훈련 (skip-gram, CBOW 사용)

#### skip-gram
train_tf_s = vec_tf_skip_gram.transform(text_train)
test_tf_s = vec_tf_skip_gram.transform(text_test)
#### CBOW
train_tf_c = vec_tf_CBOW.transform(text_train)
test_tf_c = vec_tf_CBOW.transform(text_test)

svm을 만들고 각 word2vec의 예측값과 정확도 확인

Support Vector Machine

from sklearn.svm import SVC
clf = SVC(decision_function_shape='ovo') # SVM 만들기
svc_clf_s = clf.fit(train_tf_s, label_train)  # skip-gram
svc_clf_c = clf.fit(train_tf_c, label_train)  # CBOW

예측값 뽑아내기

svc_pred_s = svc_clf_s.predict(test_tf_s) # skip-gram
svc_pred_c = svc_clf_c.predict(test_tf_c) # CBOW

정확도 확인

from sklearn import metrics
print(metrics.classification_report(label_test, svc_pred_s)) # skip-gram

print(metrics.classification_report(label_test, svc_pred_c)) # CBOW

KNN으로 머신러닝 후 정확도

K-Nearest Neighbor

from sklearn import neighbors, datasets
clf1 = neighbors.KNeighborsClassifier()
knn_clf = clf1.fit(train_tf_s, label_train)
knn_pred = knn_clf.predict(test_tf_s)

print(metrics.classification_report(label_test, knn_pred))

Random Forest로 머신러닝 후 정확도

랜덤 포레스트

from sklearn.ensemble import RandomForestClassifier
clf2 = RandomForestClassifier()
RF_clf = clf2.fit(train_tf_c, label_train)
RF_pred = RF_clf.predict(test_tf_c)
RF_pred
print(metrics.classification_report(label_test, RF_pred))
RF_clf.score(test_tf_s, label_test)

test 데이터를 public_test로 하여 text만 불러 냈습니다

public_test로 결과값 도출 및 csv저장 (KNN사용)

public_test = pd.read_csv(r'C:\Users\chlwn\Desktop\JUNO\data\smishing data\public_test.csv')
public_data = list(zip(public_test['text']))
public_text = [data[i][0] for i in range(len(data))]
import re
public_text1 = [re.sub('\d+',' ',tmp) for tmp in public_text]
public_text2 = [re.sub('\W+',' ',tmp) for tmp in public_text1]
public_text_split = [tmp.split(' ') for tmp in public_text2]
from sklearn.model_selection import train_test_split
public_text = rm_stop(public_text)
print(public_text_split)
# skip-gram
public_test_tf_s = vec_tf_skip_gram.transform(public_text_split)
# CBOW
public_test_tf_c = vec_tf_CBOW.transform(public_text_split)
print(RF_clf.predict_proba(public_test_tf_c))
S = list(zip(test_data[:], RF_clf.predict(public_test_tf_s)))
print(S)
df3 = pd.DataFrame(S)
df3.to_csv(r'C:\Users\chlwn\Desktop\JUNO\data\smishing data\public_test_RF_4.csv',encoding='UTF-8')

*이렇게 추출해서 csv 파일로 만들시 스미싱 여부가 모두 0으로 나오는데 이건 딱 봐도 잘못된 값인 것 같아서 질문을 드립니다. **

  • 이 test.csv라는 id/date/text 행만 가진 데이터를 각 id별 스미싱 확률을 가진 데이터로 내보내려면 어떻게 해야하는지 궁금 합니다.
  • knn, svm, random forest 중에 하나만 사용하면 되고 임베딩도 skip gram, cbow 중에 하나를 선택하면 됩니다. 다 사용하는 것이 아닙니다. 그나마 성능이 괜찮은 random forest 하고 skip gram 을 선택하고 진행하면 됩니다. 하는 방법을 알려달라고 하지 말고 목적을 적으세요. 하려는 목적을 알아야 하려는 방법이 맞는지 판단을 해드릴 수 있습니다. 그리고 학습된 분류기 사용방법은 이미 전 게시물에서 알려드린 것 같습니다. 정영훈 2020.1.6 15:41
  • 네 정확도를 비교하기위해서 다 써놨는데 사용할때는 ranndom forest와 skip gram,을 사용하고 진행하겠습니다. 제 목적은 학습한 데이터로 test.csv라는 스미싱 여부없이 text내용만 존재하는 데이터의 스미싱 여부를 알아내는 것입니다. 네 분류기 사용방법에 대해서 알려주신걸 확인했는데 다른 데이터인 test.csv를 불러내서 적용할때 그냥 public_test = pd.read_csv(r'C:\Users\chlwn\Desktop\JUNO\data\smishing data\public_test.csv') public_test_tf_s = vec_tf_skip_gram.transform(public_text_split) print(RF_clf.predict( public_test_tf_s)) 만 해서 뽑을시 나온 test.csv의 스미싱여부가 모두 0으로 나와서 잘못된거 같아 이렇게 질문하게되었습니다. 최준호 2020.1.6 16:12

1 답변

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)