반응형

  ## 1. 라이브러리 임포트

# import numpy as np
# import pandas as pd

import numpy as np
import pandas as pd


## 2. 파일 읽어오기

# AI-HUB 감성 대화 말뭉치 활용하여 만든 데이터 읽어오기
# final_data = pd. [칸 채우기] ('https://github.com/ohgzone/file1/raw/main/aihub_coupus.csv' )

final_data = pd.read_csv('https://github.com/ohgzone/file1/raw/main/aihub_coupus.csv' )



# 데이터 확인하기
final_data.head()

# 총 51,630건
final_data.info()

## 3. 영문, 숫자, 특수문자 제거

# '문장' 컬럼의 내용중에 영문, 특수문자 있는지 확인 : 영문과 특수문자 존재 확인
# final_data[final_data['문장'].str.contains('[^가-힣 ]')].values[:10]


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.replace('[^가-힣 ]', '', regex= True)

# '문장' 컬럼의 내용에서 영문, 특수문자 없음 확인
# final_data['문장'][final_data['문장'].str.contains('[^가-힣 ]')].sum()

final_data['문장'][final_data['문장'].str.contains('[^가-힣 ]')].sum()

# 숫자, 영문자, 특수문자 등 제거후 데이터 확인하기.
final_data.head()

## 4. 전처리 : Null, 중복 제거

# final_data 어떤 컬럼과 내용으로 되어 있는지 다시 확인
final_data.tail()

# '문장' 컬럼의 내용을 양끝의 빈공간 삭제
# final_data['문장'] = final_data['문장'].str.strip()
final_data['문장'] =final_data['문장'].str.strip()


# 데이터 다시 확인
final_data.tail()

# 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()

## 5. Label 분포 확인

# label '감정' 분포 확인 : 총 6개이며, 고루게 분포 확인. 단 기쁨이 약간 부족해 보임
# final_data['감정']. [칸 채우기] ()
final_data['감정'].value_counts()

# plot Bar차트 그리기
final_data['감정'].value_counts().plot(kind='bar')

## 6. label 숫자로 인코딩

# 라벨와 클래스을 매핑 작업

from sklearn.preprocessing import LabelEncoder
encoder = LabelEncoder()
final_data['감정'] = encoder.fit_transform(final_data['감정'])
encoder.classes_


final_data.tail()

## 7. X, Y 분리

# X, Y 분리
features = final_data['문장'].values
labels = final_data['감정'].values

features.shape, labels.shape

# features 내용 3개 출력
features[:3]

# print('이벤트 문자열 최대 길이 :{}'.format(max(len(l) for l in features)))
# print('이벤트 문자열 평균 길이 :{}'.format(sum(map(len, features))/len(features)))

print('even word max :{}'.format(max(len(l) for l in features)))
print ('event word  avg :{}'.format(sum(map(len, features))/len(features)))

# 히스토그램을 보면 30~40 부근에 많이 몰려 있음 알수 있다.

plt.hist([len(l) for l in features], bins=50)
plt.xlabel('length of samples')
plt.ylabel('number of samples')
plt.show()


## 8. train set와 test set 분리

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


# 샘플확인 , 라벨 확인
# {0: '불안', 1: '분노', 2: '상처', 3: '슬픔', 4: '당황', 5: '기쁨'}

x_train[:2], y_train[:2]

# 말뭉치를 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)



# 각 라인의 각 단어에 대한 TF-IDF 값 표현
print(x_train_v)

# 학습데이터셋의 TF-IDF 매트릭스 확인하기 : 41259 라인, 47366 단어
x_train_v.shape

## 9. 머신러닝 모델링

# 학습하는데 Colab에서 4분 소요
from sklearn.ensemble import RandomForestClassifier

rfc = RandomForestClassifier()
rfc.fit(x_train_v, y_train)
rfc.score(x_test_v, y_test)


### 10. 예측해 보기

# 출력 결과 해석 : (0, 44327) 0.241660101642553
# 0 : 첫라인, 44327 : 단어에 맵핑된 번호, 0.241660101642553 : tf-idf 계산 값
print('검증 데이터 셋의 첫번째 TF-IDF: {}'.format(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)

<br>
<br>
<br>
<br>

# 배운 내용 정리
1. AI-HUB 감정말뭉치 데이터 읽어오고
2. 데이터 전처리 : 한글, 공백외의 영어, 숫자, 특수문자등 제거
3. TF-IDF 토큰나이져 활용하여 토큰화하고 문장을 숫자로 나열
4. 머신러닝 RandomForest 모델을 활용하여 감성분류 수행


<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>

# B. LTSM 모델 이용하여 Classification하기
+ AI-HUB 감정말뭉치 데이터를 가지고
+ LSTM 모델학습하여 감정 뷴류 보겠습니다.

<br>
<br>

## 1. 라이브러리 임포트

import numpy as np
import pandas as pd

## 2. 파일 읽어오기

# AI-HUB 감성 대화 말뭉치 활용하여 만든 데이터 읽어오기
final_data = pd.read_csv('https://github.com/ohgzone/file1/raw/main/aihub_coupus.csv' )

# 데이터 확인하기
final_data.head()

# 총 51,630건
final_data.info()

## 3. 영문, 숫자 특수문자 제거

# '문장' 컬럼의 내용중에 영문, 특수문자 있는지 확인 : 영문과 특수문자 존재 확인
final_data[final_data['문장'].str.contains('[^가-힣 ]')].values[:10]

# '문장' 컬럼의 내용에서 숫자, 영문자, 특수문자등의 글자는 삭제처리
final_data['문장'] = final_data['문장'].str.replace('[^가-힣 ]','', regex=True)

# '문장' 컬럼의 내용에서 영문, 특수문자 없음 확인
final_data['문장'][final_data['문장'].str.contains('[^가-힣 ]')].sum()

# 숫자, 영문자, 특수문자 등 제거후 데이터 확인하기.
final_data.head()

## 4. 전처리 : Null, 중복 제거

# final_data 어떤 컬럼과 내용으로 되어 있는지 다시 확인
final_data.tail()

# '문장' 컬럼의 내용을 양끝의 빈공간 삭제
final_data['문장'] = final_data['문장'].str.strip()

# 데이터 다시 확인
final_data.tail()

# 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()

## 5. Label 분포 확인

# label '감정' 분포 확인 : 총 6개이며, 고루게 분포 확인. 단 기쁨이 약간 부족해 보임
final_data['감정'].value_counts()

# plot Bar차트 그리기
final_data['감정'].value_counts().plot(kind='bar')

## 6. 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)

final_data.tail()

## 7. X, Y 분리

# X, Y 분리
features = final_data['문장'].values
labels = final_data['label'].values


features.shape, labels.shape

# features 내용 3개 출력
features[:3]

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()

## 8. train set와 test set 분리

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

# 샘플확인 , 라벨 확인
# {0: '불안', 1: '분노', 2: '상처', 3: '슬픔', 4: '당황', 5: '기쁨'}

x_train[:2], y_train[:2]

## 9. 전체 문장에 대해 Tokenizing
+ 컴퓨터가 이해하기 위해 모든 단어를 숫자로 변환해야 함.
+ 단어 빈도수 따지지 않고 무조건 모든 단어 수용해서 진행

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)

## 10. texts_to_sequences : 문장을 숫자로 나열
- 빈도수 적은 단어 제외하는것 없이 모든 단어 포함해서 진행
- 그리고, 예를 들어 1번 등장하는 단어는 삭제하는 작업은 필요시 수행!!

# 문장을 숫자로 나열

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])

## 11. Padding Sequence

# 문장의 최대 길이 파악 : 제일 긴 문장 seq 길이는 38개로 구성됨.
max(len(l) for l 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 내용을 보니 잘 패딩되어 있음 확인
x_train_pad[:1]

# 문장 Seq 패딩의 shape 확인
x_train_pad.shape, x_test_pad.shape

## 12. LSTM 모델링

from tensorflow.keras.layers import Dense, Flatten, Conv2D, 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.keras'
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])

epochs = range(1, len(history.history['accuracy']) + 1)
plt.plot(epochs, history.history['accuracy'])
plt.plot(epochs, history.history['val_accuracy'])
plt.title('model accuracy')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'valid'], )
plt.show()

model.evaluate(x_test_pad, y_test)

### 13. 예측해 보기

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)]}')

반응형

'Google > Photo' 카테고리의 다른 글

이미지  (0) 2024.09.04
구글 포토(Google Photo) 사진 다운로드하기 (부분 or 일괄)  (1) 2020.12.27