저번글에서 임베딩을 해보았고 오늘은 임베딩한 벡터값들을 이용해서 본격적인 모델에 적용하는 과정이다.
with open('/content/drive/MyDrive/Personal Project/Classify_fake-news/train_data.pkl', 'rb') as f:
train_set = pickle.load(f)
with open('/content/drive/MyDrive/Personal Project/Classify_fake-news/test_data.pkl', 'rb') as f:
test_set = pickle.load(f)
우선 train_set이라는 데이터파일과 test_set파일들을 불러온다. 파일들의 확장자가 pkl로 되어 있는 이유는 각단어마다 임베딩한 벡터값들이 [1.xx, 2.xxx,3.xxx] 이런식으로 list형으로 되어있는데 이걸 csv파일로 저장하면 저 값들을 리스트형이 아니라 문자열로 인식해버리기 때문에 train_set과 test_set을 pkl로 저장해놨었다.
# sentence에 clean_text를 저장
train_sentence = list([i for i in train_set['clean_text']])
test_sentence=list([i for i in test_set['clean_text']])
# 문장을 이용하여 단어와 벡터를 생성
train_model = Word2Vec(train_sentence, size=100, window=5, min_count=0, workers=1)
test_model = Word2Vec(test_sentence, size=100, window=5, min_count=0, workers=1)
train_sentetce에 train_set 데이터의 정제된 본문을 넣어주고, 마찬가지로 test_sentence에 test_set 데이터의 정제된 본문을 넣어준다. 이후 저번시간에 했던 것처럼 각각 test, train모델을 생성해준다.
여기까지는 순조롭게 진행했었는데, 그 다음이 문제였다. 이 임베딩한 벡터들을 모델에 적용해야되는데 내가 생성한 처음 모델에는 각각의 한 문장이 100개의 차원으로 설정했으므로 100개의 임베딩 벡터로 구성되어있었다. 한 문장당 벡터가 100개이므로 문장의갯수*100개의 벡터가 들어가있었는데 모델에 넣으려면 각 문장당 하나의 벡터로 매치가 되어있어야 했다. 그래서 찾아본 방법이 여러개 있었는데, word2vec을 통한 모델링 말고 sentence2vec등의 문장들을 임베딩하는 방법들도 있었다.
나는 그냥 100개의 벡터들을 평균을 내서 구하는 방식을 사용하였는데, 나중에 안사실이지만 이 방법에는 큰 문제가 있다. 내가 사용한 방법처럼 문장에서 각 단어들의 임베딩벡터값들을 단순 더해서 평균 내버리면 아래와 같은 두 문장이 있을 때 의미가 정반대인데 둘의 평균벡터는 같게 나온다는 것이다. 처음에는 이걸 몰랐기 때문에 그냥 진행했었다. 나중에는 이 방법말고 문장자체를 임베딩하는 방법을 찾아봐야 할 것 같다.
our president is a good leader he will not fail
our president is not a good leader he will fail
embedding_dim = 100
zero_vector = np.zeros(embedding_dim)
def calc_sentence_vector(sentence,model):
if len(sentence) != 0:
return sum([model.wv[word] for word in sentence if word!=None])/len(sentence)
else:
return zero_vector
# 각 문장의 평균벡터 만들기
all_train_vect=[]
for i in train_set['clean_text']:
sentence_vect=calc_sentence_vector(i,train_model)
all_train_vect.append(sentence_vect)
train_set = train_set.assign(vect = all_train_vect)
#-------------------------------------------------------
all_test_vect=[]
for i in test_set['clean_text']:
sentence_vect=calc_sentence_vector(i,test_model)
all_test_vect.append(sentence_vect)
test_set = test_set.assign(vect = all_test_vect)
이렇게 문장벡터를 생성했다.
이제 마지막으로 모델에 적용해볼 것이다. 모델들에 대한 더 자세한 설명은 다른 글에 작성하고 여기서는 그냥 모델들데 데이터를 적용하는 것만 보여주겠다.
x_train=train_set['vect']
y_train=train_set['bool']
x_test=test_set['vect']
y_test=test_set['bool']
x_train=[i for i in x_train]
y_train=[i for i in y_train]
x_test=[i for i in x_test]
y_test=[i for i in y_test]
우선 방금 생성한 문장 임베딩 벡터를 x에 fit하고, y에는 fake, true를 나타내는 bool column의 값을 fit 한다.
밑에 list comprehension을 사용한 이유는 데이터를 집어넣다보니까 list형식이 아니라서 오류가 뜨길래 해줬다.
랜덤포레스트
rfc = RandomForestClassifier(random_state=1)
rfc.fit(x_train, y_train)
y_pred = rfc.predict(x_test)
print(f'Model train accuracy: {rfc.score(x_train, y_train)*100:.3f}%')
print(f'Model test accuracy: {rfc.score(x_test, y_test)*100:.3f}%')
print(f'Model test precision: {precision_score(y_pred,y_test):.3f}')
print(f'Model test recall: {recall_score(y_pred,y_test):.3f}')
print(f'Model test f1_score: {f1_score(y_pred,y_test):.3f}')
위 코드는 랜덤 포레스트 분류를 사용하고 평가지표인 accuracy, precision, recall, fl_score을 계산한 것이다.
생각보다 분류가 잘 나와서 놀랐다. 위에서 말했듯이 문장 임베딩 벡터를 만들 때 치명적인 오류가 있었는데도 값이 잘 나와서 다행이었다.
KNN
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(x_train, y_train)
y_pred = knn.predict(x_test)
print(f'Model train accuracy: {knn.score(x_train, y_train)*100:.3f}%')
print(f'Model test accuracy: {knn.score(x_test, y_test)*100:.3f}%')
print(f'Model test precision: {precision_score(y_pred,y_test):.3f}')
print(f'Model test recall: {recall_score(y_pred,y_test):.3f}')
print(f'Model test f1_score: {f1_score(y_pred,y_test):.3f}')
위 코드는 knn분류에 n을 5로 설정하고 돌려봤다.
가우시안 나이브 베이즈
nb = GaussianNB()
nb.fit(x_train, y_train)
y_pred =nb.predict(x_test)
print(f'Model train accuracy: {nb.score(x_train, y_train)*100:.3f}%')
print(f'Model test accuracy: {nb.score(x_test, y_test)*100:.3f}%')
print(f'Model test precision: {precision_score(y_pred,y_test):.3f}')
print(f'Model test recall: {recall_score(y_pred,y_test):.3f}')
print(f'Model test f1_score: {f1_score(y_pred,y_test):.3f}')
가우시안 나이브베이즈 역시 분류 결과가 높게 나왔다.
SVC
clf = LinearSVC(max_iter=100, C=1.0)
clf.fit(x_train, y_train)
y_pred = clf.predict(x_test)
print(f'Model train accuracy: {clf.score(x_train, y_train)*100:.3f}%')
print(f'Model test accuracy: {clf.score(x_test, y_test)*100:.3f}%')
print(f'Model test precision: {precision_score(y_pred,y_test):.3f}')
print(f'Model test recall: {recall_score(y_pred,y_test):.3f}')
print(f'Model test f1_score: {f1_score(y_pred,y_test):.3f}')
svc분류기는 비교적 수치가 낮았지만 이정도면 그래도 준수했다.
느낀점
우선 프로젝트는 끝났는데, 아직 뭔가 남는게 안느껴졌다. 그냥 어떻게 하는지 배우고, 그 코드를 찾아서 복붙한 느낌?... 그래도 나름대로 임베딩에 대해서 알아보고, 단어 임베딩 된 벡터들을 넣을 수 없자 평균벡터를 생성해보자 라는 생각등의 뭔가는 있었는데, 음 ..데이터분석이 이런건가 싶었다. 전체적인 과정을 요약해보겠다.
목적은 가짜와 진짜 뉴스를 분류하는 것이었고, 각각의 뉴스들을 임베딩한뒤 분류모델을 통해서 분류하였다.
우선 데이터의 TEXT 부분만을 사용했고, 불용어 제거등의 단어들을 전처리한 뒤, 각각의 본문을 100개의 차원으로 임베딩해준뒤에 각 문장의 단어들의 평균벡터를 통해서 문장 벡터를 만들어내고 그 문장 벡터들의 값을 모델에 넣었다.
첫번째 아쉬운점은 사실 아직 모델들이 어떻게 돌아가는지 잘 모르겠다. 단어들을 정제하고 그런 것까진 그냥 했는데, 임베딩을 하라해서 임베딩을 했다. 그런데 이게 모델에 넣으면 어떻게 분류해주는지를 잘 모르겠다. 난 가짜뉴스와 진짜뉴스의 본문을 임베딩했는데 이 임베딩벡터의 유사도를 통해서 분류를 한 것인가?.. 이거는 모델들을 하나 하나 자세하게 공부하면서 어떻게 작동한건지 알아봐야겠다.
다음 글에는 EDA를 추가한 코드와 전체코드를 정리해서 올리고 분류모델들은 각각 알고리즘 카테고리에 올릴것이다.
'프로젝트 > 가짜 뉴스 분류' 카테고리의 다른 글
[가짜뉴스구별]-Final (0) | 2022.06.28 |
---|---|
[가짜뉴스구별]-Day 2(임베딩구현) (0) | 2022.04.02 |
[가짜뉴스구별]-Day 1(임베딩 설명) (0) | 2022.04.02 |
[가짜뉴스구별]-Day 0 (0) | 2022.03.28 |