Silver bullet
text 분류 실습 코드 본문
RandomForest 모델 활용 : 감성분류
import numpy as np
import pandas as pd
# AI-HUB 감성 대화 말뭉치 활용하여 만든 데이터 읽어오기
final_data = pd.read_csv('https://github.com/ohgzone/file1/raw/main/aihub_coupus.csv')
# 총 51,630건
final_data.info()
# boolean indexing
# 영문, 숫자, 특수문자 제거
final_data[final_data['문장'].str.contains('[^가-힣 ]')]
# '문장' 컬럼의 내용중에 영문, 특수문자 있는지 확인 : 영문과 특수문자 존재 확인
final_data[final_data['문장'].str.contains('[^가-힣 ]')].values[:10]
# '문장' 컬럼의 내용에서 숫자, 영문자, 특수문자등의 글자는 삭제처리
# final_data['문장'].replace('[^가-힣 ]','', regex=True) : 이렇게도 가능
final_data['문장'] = final_data['문장'].str.replace('[^가-힣 ]','', regex=True)
# '문장' 컬럼의 내용에서 영문, 특수문자 없음 확인
final_data['문장'][final_data['문장'].str.contains('[^가-힣 ]')].sum()
# '문장' 컬럼의 내용을 양끝의 빈공간 삭제
final_data['문장'] = final_data['문장'].str.strip()
# Null 있는지 확인 : 없음
final_data.isnull().sum()
# 중복 데이터 있는지 확인 : 56건 중복 존재 확인
final_data['문장'].duplicated().sum()
# 중복 데이터 제거
final_data.drop_duplicates(subset=['문장'], inplace=True)
# 기존 51,630건 --> 이후 51,574건 : 56건 중복 삭제 확인
final_data.info()
# label '감정' 분포 확인 : 총 6개이며, 고루게 분포 확인. 단 기쁨이 약간 부족해 보임
final_data['감정'].value_counts()
# plot Bar차트 그리기
final_data['감정'].value_counts().plot(kind='bar')
# 라벨와 클래스을 매핑 작업
from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
final_data['감정'] = encoder.fit_transform(final_data['감정'])
encoder.classes_
# X, Y 분리
features = final_data['문장'].values
labels = final_data['감정'].values
features.shape, labels.shape
print('이벤트 문자열 최대 길이 :{}'.format(max(len(l) for l in features)))
print('이벤트 문자열 평균 길이 :{}'.format(sum(map(len, features))/len(features)))
# 히스토그램을 보면 30~40 부근에 많이 몰려 있음 알수 있다.
plt.hist([len(s) for s in features], bins=50)
plt.xlabel('length of samples')
plt.ylabel('number of samples')
plt.show()
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(features, labels , test_size=0.2, stratify=labels, random_state=41)
x_train.shape, x_test.shape, y_train.shape, y_test.shape
# 말뭉치를 TF-IDF로 변환하기
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer()
x_train_v = tfidf.fit_transform(x_train)
x_test_v = tfidf.transform(x_test)
# 중요 : test는 transform만 하자
# 학습하는데 Colab에서 4분 소요
from sklearn.ensemble import RandomForestClassifier
rfc = RandomForestClassifier() # 모델 정의
rfc.fit(x_train_v, y_train) # 모델 학습
rfc.score(x_test_v, y_test)
# 0.5
# 출력 결과 해석 : (0, 44327) 0.241660101642553
# 0 : 첫라인, 44327 : 단어에 맵핑된 번호, 0.241660101642553 : tf-idf 계산 값
print(f'검증데이터셋의 첫번째 TF-IDF : {x_test_v[0]}')
print(f'검증데이터셋의 첫번째 TF-IDF 역변환 : {tfidf.inverse_transform(x_test_v[:1])}')
# RandomForest 모델로 예측하기
predict = rfc.predict(x_test_v[:1])
predict, encoder.inverse_transform(predict)
LSTM 모델 이용하여 classification하기
label로 숫자 인코딩
# 감정 리스트 만듬
list1 = final_data['감정'].value_counts().index.values
list1
# 라벨와 클래스을 매핑 작업
label2class = {}
class2label = {}
for cl, la in enumerate(list1):
# print(i, j)
label2class[la] = cl
class2label[cl] = la
print(label2class)
print(class2label)
# '감정' 라벨링 수행
final_data['label'] = final_data['감정'].map(label2class)
# X, Y 분리
features = final_data['문장'].values
labels = final_data['label'].values
print('이벤트 문자열 최대 길이 :{}'.format(max(len(l) for l in features)))
print('이벤트 문자열 평균 길이 :{}'.format(sum(map(len, features))/len(features)))
# 히스토그램을 보면 30~40 부근에 많이 몰려 있음 알수 있다.
plt.hist([len(s) for s in features], bins=50)
plt.xlabel('length of samples')
plt.ylabel('number of samples')
plt.show()
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(features, labels , test_size=0.2, stratify=labels, random_state=41)
x_train.shape, x_test.shape, y_train.shape, y_test.shape
import tensorflow as tf
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
# Tokenizer 구현 : 단어 사전 만들기(fit_on_texts)
tokenizer = Tokenizer()
tokenizer.fit_on_texts(x_train)
# 단어에 대한 숫자 매핑
print(tokenizer.word_index)
# 반대로 숫자로 단어 매핑
print(tokenizer.index_word)
# 단어별 빈도수 확인
print(tokenizer.word_counts)
# 총 단어 갯수 : 47,646
max_words = len(tokenizer.index_word)
print(max_words)
# 문장을 숫자로 나열
x_train_seq = tokenizer.texts_to_sequences(x_train)
x_test_seq = tokenizer.texts_to_sequences(x_test)
# 문장을 숫자로 변경후 갯수 확인
# x_train.shape, x_test.shape, y_train.shape, y_test.shape : ((41259,), (10315,), (41259,), (10315,))
print(len(x_train_seq), len(x_test_seq))
print(x_train[1:3])
print(x_train_seq[1:3])
# 문장의 최대 길이 파악 : 제일 긴 문장 seq 길이는 38개로 구성됨.
max(len(line) for line in x_train_seq)
# 모든 문장을 최대 문장 Seq 길이 38에 맞춘다.
x_train_pad = pad_sequences(x_train_seq, maxlen=38)
x_test_pad = pad_sequences(x_test_seq, maxlen=38)
# 문장 Seq 패딩의 shape 확인
x_train_pad.shape, x_test_pad.shape
from tensorflow.keras.layers import Dense, Flatten, Conv1D, MaxPool2D
from tensorflow.keras.layers import Embedding, Bidirectional, LSTM, SimpleRNN, GRU
from tensorflow.keras.models import Sequential
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
# 하이퍼 파라미터
max_words = 47646 + 1 # 총 단어 갯수 + padding 0 번호
max_len = 38 # 최대 문장 길이
embedding_dim = 32 # embedding 차원
# 모델 선언
model = Sequential()
# 단어를 의미있는 32 차원으로 Vector 변경(Embedding)
model.add(Embedding(max_words, embedding_dim, input_length=max_len))
# LSTM 모델
model.add(LSTM(16, return_sequences=True))
model.add(LSTM(16, return_sequences=True))
model.add(Flatten())
model.add(Dense(128, activation='swish'))
model.add(Dense(32, activation='swish'))
model.add(Dense(6, activation='softmax'))
# 모델 compile
model.compile(loss = 'sparse_categorical_crossentropy',
optimizer = 'adam',
metrics = 'accuracy')
model.summary()
# 조기종료 콜백함수 정의(EarlyStopping)
es = EarlyStopping(monitor='val_loss', patience=10, verbose=1)
# 체크포인트 저장(ModelCheckpoint)
checkpoint_path = 'tmp_checkpoint.ckpt'
cp = ModelCheckpoint(checkpoint_path, monitor='val_loss', verbose=1, save_best_only=True)
# 모델 학습(fit)
history = model.fit(x_train_pad, y_train, epochs=50, batch_size=512,
validation_split=0.2, verbose =1, callbacks=[es, cp])
model.evaluate(x_test_pad, y_test)
323/323 [==============================] - 1s 4ms/step - loss: 4.8239 - accuracy: 0.3923
[4.823884963989258, 0.3923412561416626]
print(f'문자열 : {x_test[0]}')
print(f'Sequence : {x_test_pad[0]}')
# 모델 예측하기(predict)
predict = model.predict(x_test_pad[:1])
print(f'True : {class2label[y_test[0]]}')
print(f'Predict : {class2label[np.argmax(predict)]}')'AI > AI' 카테고리의 다른 글
| Fashion-MNIST & cats-and-dogs data set & CIFAR-10 (0) | 2024.07.13 |
|---|---|
| Bayesian-Search HPO with Scikit-Optimize (0) | 2024.07.13 |
| Convolutional Neural Network (CNN) 이론 & 구현 실습 (0) | 2024.07.13 |
| Tensorflow (version 2 code) - Universal Approximation Theorem & Statsmodels (0) | 2024.07.13 |
| DL - Tensorflow (version 2 code) Classification & Regresstion 요약 (0) | 2024.07.13 |