<jupyter_start><jupyter_text>네이버 쇼핑몰 리뷰데이터  데이터 가져오기<jupyter_code>## !python -m pip install konlpy<jupyter_output><empty_output><jupyter_text>오픈 api 사용할 때 쓰는 것 : curl<jupyter_code>## !curl -O https://raw.githubusercontent.com/konlpy/konlpy/master/scripts/mecab.sh<jupyter_output><empty_output><jupyter_text>리눅스 파일 확장자 : .sh(shell)<jupyter_code>##  !bash ./mecab.sh
## !curl -O https://raw.githubusercontent.com/bab2min/corpus/master/sentiment/naver_shopping.txt<jupyter_output><empty_output><jupyter_text>다운받은 데이터 판다스로 불러오기<jupyter_code>import pandas as pd
total_data = pd.read_table('./naver_shopping.txt', names=['ratings','reviews'])
total_data.head(10)
total_data.info()<jupyter_output><class 'pandas.core.frame.DataFrame'>
RangeIndex: 200000 entries, 0 to 199999
Data columns (total 2 columns):
 #   Column   Non-Null Count   Dtype 
---  ------   --------------   ----- 
 0   ratings  200000 non-null  int64 
 1   reviews  200000 non-null  object
dtypes: int64(1), object(1)
memory usage: 3.1+ MB<jupyter_text>[Drop_duplicates](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.drop_duplicates.html)(동일하게) 되있는 부분을 없애기 ``` 0   ratings  200000 non-null  int64  1   reviews  200000 non-null  object ``` 와  len(total_data) 199908   비교해보니 다른게 있는 것을 알 수 있었다.<jupyter_code>total_data.drop_duplicates(subset=['reviews'], inplace=True)
len(total_data)<jupyter_output><empty_output><jupyter_text>split<jupyter_code>from sklearn.model_selection import train_test_split<jupyter_output><empty_output><jupyter_text>전처리<jupyter_code>x_data = total_data['reviews']
y_data = total_data['ratings']
x_train ,x_test,y_train, y_test = train_test_split(x_data,y_data)
x_train.shape, y_train.shape, x_test.shape, y_test.shape
y_data.value_counts().plot(kind='bar')<jupyter_output><empty_output><jupyter_text>데이터가 쏠려있을 때 평준화 시켜줘야 한다(많은건 삭제:과소표집, 적은건 증가 시킴:과대표집)[SMOTE](https://imbalanced-learn.org/stable/references/generated/imblearn.over_sampling.SMOTE.html)<jupyter_code>type(x_train)<jupyter_output><empty_output><jupyter_text>NLP : 테스트 전처리[regular expression](https://regexr.com/)불용어 처리 간단히 하는 방법한글만 가져올 때 가나다 순으로 [^가-힣] 모두 가져올 수 있음 가나다 순으로 [^가-두] 사이는 모두 가져올 수 있음[^가-힣ㄱ-ㅎㅠ ]이런식으로 추가해서 가져오면 됨한글과 영어 같이 가져올때 [^가-두a-l]<jupyter_code>x_temp = x_train
x_temp.str.replace('[가-힣ㄱ-ㅎㅠ ]','')
x_temp01= x_train
x_temp01.str.replace('[^가-힣ㄱ-휴 ]','')
x_train.str.replace('[^가-힣ㄱ-ㅎㅠ ]','') # [a-zA-Z ]
from konlpy.tag import Mecab
mecab = Mecab()
print(mecab.morphs('와 이런 것도 상품이라고 차라리 내가 만드는게 나을 것 같다.'))
x_train_small = x_train[0:5000]
sentance = list()
stopwords = ['도', '는', '다', '의', '가', '이', '은', '한', '에', '하', '고', '을', '를', '인', '듯', '과', '와', '네', '들', '듯', '지', '임', '게']

for tok in x_train_small:
  encoded = mecab.morphs(tok)

  sentance.append([item for item in encoded if item not in stopwords])

sentance<jupyter_output><empty_output><jupyter_text>Tokenizer<jupyter_code>print(sentance)
import tensorflow as tf
tokenizer = tf.keras.preprocessing.text.Tokenizer()
tokenizer.fit_on_texts(sentance)
 tokenizer.word_index<jupyter_output><empty_output><jupyter_text>우리가 만든 사전의 단어가 전체문장에 몇번 들어갔는지 카운팅 되어 나옴<jupyter_code>tokenizer.word_counts<jupyter_output><empty_output><jupyter_text>전체카운팅에서 낮은 애들 걸러내기카운트 2이하인 것들만 뽑아내서 전체에서 빼면 총 몇퍼센트 인지 확인가능하다<jupyter_code>total_cnt = len(tokenizer.word_index)
rare_cnt = 0
total_freq,rare_freq = 0,0

for key, value in tokenizer.word_counts.items():
  total_freq = total_freq + value #전체 단어의 수
  if(value <=2):
    rare_cnt = rare_cnt+ 1  
    rare_freq = rare_freq + value #2미만인 단어(희귀단어)의 수
total_cnt, rare_cnt, (rare_cnt/total_cnt)*100, (rare_freq/total_freq)*100
vocab_size = total_cnt - rare_cnt #보케블러리 사이즈<jupyter_output><empty_output><jupyter_text>oov(Out Of Vocablary)<jupyter_code>tokenizer = tf.keras.preprocessing.text.Tokenizer(vocab_size, oov_token='OOV')
tokenizer.fit_on_texts(sentance)
 tokenizer.index_word<jupyter_output><empty_output><jupyter_text>숫자화텍스트 시퀀스<jupyter_code>x_train_small = tokenizer.texts_to_sequences(sentance)
len(x_train_small[0]),len(x_train_small[40]),len(x_train_small[50])<jupyter_output><empty_output><jupyter_text>평균적인 사이즈 확인<jupyter_code>hist_len = [len(words) for words in x_train_small]
import matplotlib.pyplot as plt
plt.hist(hist_len, bins=50)<jupyter_output><empty_output><jupyter_text>pad를 몇정도 하면 좋을지 확인<jupyter_code>sum(hist_len)/ len(x_train_small)<jupyter_output><empty_output><jupyter_text>50정도로 pad채워주기로함<jupyter_code>x_train_small =tf.keras.preprocessing.sequence.pad_sequences(x_train_small, maxlen=50)
x_train_small<jupyter_output><empty_output><jupyter_text>모든 데이터가 너무많아서 5000개만 뽑아서 스몰로 해줌<jupyter_code>y_train_small = y_train[0:5000]<jupyter_output><empty_output><jupyter_text>전체 y_train_small 값에서 -1 해주기카테고리가 원핫인코딩 되도 0으로 시작해도 본래 모습으로 쓸수 있기 때문에<jupyter_code>import numpy as np

np.unique(y_train_small) # 원래는 별점이 5개, 의견은 데이터 기준이어서 3이빠졋으니 덴스 5개
y_train_small = np.array(y_train_small)-1
np.unique(y_train_small) # 맥스4 기준으로 4,3,2,1,0써줘서  덴스 5개
len(x_train_small), len(y_train_small)<jupyter_output><empty_output><jupyter_text>Model<jupyter_code>model = tf.keras.models.Sequential()<jupyter_output><empty_output><jupyter_text>스파스 카테고리칼 크로스엔트로피는 내부에서 자동으로 y의 값이 1,2,3,4 이런식으로 숫자로 들어오면 원핫인코딩으로 바꿔줌. (분류형)내부적으로 원핫인코딩으로 바꿔질때 규칙이 있다.y에 나열된 값이 0부터 시작되고 맥시멀값을 쫒는다.```np.unique(y_train_small)array([1, 2, 4, 5])```이경우 그래서 6개가 된다.(0,1,2,3,4,5)-> 덴스 6<jupyter_code>model.add(tf.keras.layers.Embedding(input_dim= vocab_size, output_dim =30 ,input_length=50))
# model.add(tf.keras.layers.LSTM(128))
# model.add(tf.keras.layers.GRU(128))
model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(128)))
model.add(tf.keras.layers.Dense(5,activation='softmax'))

model.compile(optimizer='adam', loss = 'sparse_categorical_crossentropy', metrics=['acc'])<jupyter_output><empty_output><jupyter_text>성능 높이는 방법 1: 노드 바꿔주기``` model.add(tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(128))) ``` 성능 높이는 방법 2: LSTM 기능 보강```model.add(tf.keras.layers.GRU(128))```<jupyter_code>hist = model.fit(x_train_small, y_train_small, epochs=50, batch_size=256, validation_split=0.3, shuffle=True)
model.evaluate(x_train_small, y_train_small) # LSTM(128) loss: 1.2520 - acc: 0.4249
import matplotlib.pyplot as plt
plt.plot(hist.history['loss'])
plt.plot(hist.history['val_loss'],'b-')
plt.show()
plt.plot(hist.history['acc'])
plt.plot(hist.history['val_acc'],'r-')
plt.show()
model.evaluate(x_train_small, y_train_small) # GRU(128) loss: 0.0688 - acc: 0.9823
plt.plot(hist.history['loss'])
plt.plot(hist.history['val_loss'],'b-')
plt.show()
plt.plot(hist.history['acc'])
plt.plot(hist.history['val_acc'],'r-')
plt.show()
model.evaluate(x_train_small, y_train_small) # Bidirectinal(LSTM(128)) loss: 0.1749 - acc: 0.9477
plt.plot(hist.history['loss'])
plt.plot(hist.history['val_loss'],'b-')
plt.show()
plt.plot(hist.history['acc'])
plt.plot(hist.history['val_acc'],'r-')
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1535438800756804, 'fraction_numerical': 0.029253383786930577, 'mean_word_length': 7.14218009478673, 'pattern_counts': {'":': 0, '<': 90, '<?xml version=': 0, '>': 90, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '22', 'dir': 'jupyter-structured-clean-dedup', 'id': '206116', 'license': 'Apache-2.0', 'n_tokens_mistral': 3620, 'n_tokens_neox': 3842, 'n_words': 465, 'path': 'Naver_shopping.ipynb', 'repo_name': 'ginttone/multi_deeplearning', 'size': '6871'}