반응형

안녕하세요.

 

오늘은 이전 포스팅 RNN 이론에 이어 LSTM 이론 및 실습을 하도록 하겠습니다.

 

실습은 "Tensorflow 2.0 beta" 버전으로 RNN을 구축하겠습니다!

 


 

먼저,

 

LSTM(Long Short-term Memory)에 대해 알아보겠습니다.

 

 

Part 1. 이론

 

LSTM은 RNN의 Gradient Vanishing 문제를 해결하기 위해 도입되었습니다.

 

LSTM 구조의 기본 원리는

신경망이 장기적인 관계를 학습을 위하여

중요한 정보를 확실하게 전송할 목적으로 설계되었다는 것입니다.

 

[RNN 과 LSTM 비교]

그림 출처: https://ratsgo.github.io

 

 

1. 유지 게이트(keep/forget gate): 얼마나 많은 양의 이전 메모리를 유지할지 결정

 

이전 시간 단계에서 메모리 상태 텐서는 정보가 풍부하지만,

 

일부 정보는 오래된 것일 수 있다.

 

 

2. 쓰기 게이트(write/input gate): 어떤 정보를 메모리 상태에 기록해야 할 것인지 결정

 

1) 어떤 정보를 쓰려는지 알아 낸다.

 

2) 계산된 텐서가 새로운 상태를 포함하길 원하는지, 이전의 값을 전달하길 원하는지 파악한다.

 

 

3. 출력 게이트(output gate): 시간 단계마다 LSTM 유닛 출력

 

1) tahnh 층은 중간 텐서를 생성한다.

 

2) 시그모이드 층은 현재 입력과 이전 출력을 사용해 비트 텐서 마스크를 생성한다.

 

3) 중간텐서는 최종 출력을 생성하기 위해 비트 텐서와 곱해진다.

 


 

Part2. 실습

 

우선 Tensorflow 2.0 버전을 설치하겠습니다.

 

!pip install -q tensorflow==2.0.0-beta1

!pip install -q tensorflow-gpu==2.0.0-beta1  # gpu 버전

 

 

두 문장이 유산한지(NLP) 예측하는 LSTM 모델을 구현하였습니다.

 

data: 캐글 대회 중 하나인 "Quora Question Pairs"

(단, 데이터 전처리는 다루지 않습니다.)

 

import tensorflow as tf
from sklearn.model_selection import train_test_split # 데이터 셋 분할
import numpy as np
import pandas as pd
import json

train_input, test_input, train_label, test_label = train_test_split(input_data, label_data, test_size=0.2, random_state=2019)

VOCAB_SIZE = input_data.max()+1
WORD_EMBEDDING_DIM = 64
BUFFER_SIZE = 10000
BATCH_SIZE = 16

train_dataset = tf.data.Dataset.from_tensor_slices((train_input, train_label))
test_dataset = tf.data.Dataset.from_tensor_slices((test_input, test_label))

train_dataset = train_dataset.shuffle(BUFFER_SIZE)
train_dataset = train_dataset.batch(BATCH_SIZE)

test_dataset = test_dataset.batch(BATCH_SIZE)

model = tf.keras.Sequential([
    tf.keras.layers.Embedding(VOCAB_SIZE, WORD_EMBEDDING_DIM),    # 자연어 처리 핵심 함수
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64, return_sequences=True)),
    tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(32)),
    tf.keras.layers.Dense(64, activation='relu'),
    tf.keras.layers.Dropout(rate=0.2),
    tf.keras.layers.Dense(1, activation='sigmoid')
])

model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])
              
# 모델 훈련
history = model.fit(train_dataset,
                    epochs=10,
#                     validation_data=test_dataset
                   )

 

[결과]

(케글에서 제공하는 test 데이터에 대한 결과는 케글에 제출하면 확인 가능합니다.)

 

[train_accuracy]
[train loss]

 

여기에서는 단층의 얕은 모델을 만들어서 유사도를 측정하였습니다.

 

추가로 더 깊은 모델을 만들어서 성능을 높여 보세요~


LSTM 이론 출처: 딥러닝의 정석

반응형
반응형

안녕하세요~



"현업에서 많이 사용하고 있는 Python 모듈 마스터하기!"


라는 시리즈를 포스팅하려고 합니다.



그 중 첫 번째편은 바로 Pandas 입니다!




Pandas의 DataFrame의 형태가 데이터베이스의 테이블과 유사하기 때문에 많이 사용되지 않을까요? :)


즉, Feature 엔지니어링 하여 데이터 분석을 할 때 유용합니다!



1. Series


그렇다면, 먼저 Pandas의 기본 자료구조인 Series에 대해 알아보겠습니다.



Series = value(값) + Index(인덱스)


Series는 1차원 배열과 같은 구조로 동일한 자료형만 담을 수 있습니다.




예) Series 생성

import pandas as pd


s = pd.Series([172, 160, 174, 183], index=["지수", "으니", "덕", "운동"])


# 딕셔너리 개체로 시리즈를 생성할 수 있다.

s2 = pd.Series({"지수": 172, "으니": 160, "덕": 174, "운동": 183})


# 순서를 정하고 싶다면 인덱스를 지정해야한다.

s3 = pd.Series({"지수": 172, "으니": 160, "덕": 174, "운동": 183}, index=["지수","으니","덕","운동"])

결과)



예2) Series 인덱싱

s["으니":"덕"]


# 위와 같은 결과

s[1:3]


# Series[conditions]: conditions 부분에 논리연산이 올 수 있다

s[(160 == s) | (174 == s)]

결과)



예3) Series 특징


시리즈 객체는 라벨 값에 의해 인덱싱이 가능하므로 딕셔너리 자료형과 같다고 할 수 있다.


# items(): dictionary method인 items함수는 key와 value의 쌍을 튜플로 묶은 값을 dict_items 객체로 돌려준다.

for k, v in s.items():

print("%s's 키는 %d cm 입니다." % (k,v))



예4) 데이터 갱신, 추가, 삭제

# 갱신

s["으니"] = 161


# 추가

s["다래"] = 179


# 삭제

del s["운동"]

결과) 갱신


결과) 추가


결과) 삭제




2. DataFrame


Series가 복수개 합쳐진 것

서로 다른 종류의 데이터 타입을 가질 수 있으며,

행렬의 열, 행에 인덱스 값을 부여한 것과 같습니다.



예) DataFrame 생성

import pandas as pd


data = {

"키": [172, 160, 174, 183],

"나이": [25, 24, 27, 26],

"성별" : ['F', 'F', 'M', 'M']

}

columns = ["키", "나이", "성별"]

index = ["지수", "으니", "덕", "운동"]

df = pd.DataFrame(data, index=index, columns=columns)

df.index.name = "이름"

결과)



예2) DataFrame 인덱싱

# 열 인덱싱

df["키"]


# 행 인덱싱1

df["으니":"덕"]


# 행 인덱싱2: 행단위로 인덱싱을 하고자 하면 항상 슬라이싱을 해야한다 df[1:3]


# .iloc[] 을 이용한 인덱싱: 행단위로 인덱싱 (without 슬라이싱) df.iloc[1]


# .loc[condition] 을 이용한 인덱싱

df.loc[df["키"] <= 160]

결과) 열 인덱싱


결과) 행 인덱싱




예3) Transpose

df.T # 대부분의 np 2차원 배열이 가지는 속성/메소드를 지원한다.

결과)



예4) 갱신, 삽입, 삭제

# 갱신

df.loc["으니","키"] = 161

# df["키"].loc["으니"] = 161 # warning


# 열 삽입1

df["학과"] = ["경영","경영정보","경영정보","도시 부동산"]


# 열 삽입2

df["학과"] = pd.Series(["경영","경영정보","경영정보","도시 부동산"], index=["지수","으니","덕","운동"])


# 행 삽입1

df.loc["다래"] = {"키": 179, "나이": 24, "성별": "F", "학과": "응급의학과"}


# 행 삽입2

df.loc["다래"] = pd.Series([179, 'F', '응급의학과'], index=["키","성별","학과"]) # 나이: NaN 발생


# 삭제: del, drop 키워드를 사용하면 열을 삭제할 수 있다.

결과) 갱신


결과) 열 삽입


결과) 행 삽입



예5) DataFrame 변형

df1 = pd.DataFrame({"키":[161,179], "이름":["으니","다래"], "나이":[24,24], "학과": ["경영정보","응급의학"]}, \

columns=["키","이름","학과"]) df2 = pd.DataFrame({"학과":["경영","경영정보","도시부동산"], "학과번호":[201,202,203]}, columns=["학과","학과번호"])


# merge()

df = pd.merge(df1,df2,on="학과") # inner join과 같은 결과, on : 기준 key 값

df = pd.merge(df1,df2, how='left') # left: df1 | right: df2 의 키값을 모두 보여준다

df = pd.merge(df1,df2, how='outer') # 키값이 한쪽에만 있어도 데이터를 보여준다.


# concat()

df1 = pd.DataFrame({"키":161, "이름":"으니", "나이":24, "학과": "경영정보"}, columns=["키","이름","학과"], \

index = [0]) df2 = pd.DataFrame({"키":[174,183], "이름":["덕","운동"], "나이":[27,26], "학과": ["경영정보","도시부동산"]}, \

columns=["키","이름","학과"], index = [1,2])

df = pd.concat([df1,df2], ignore_index=True)

결과) merge()


결과) concat()



※참고: merge()와 concat()의 차이점


.merge()는 두 데이터 프레임의 공통 열 또는 인덱스를 기준으로 두 테이블을 합친다.


이때 기준이 되는 열, 행의 데이터를 키(key)라고 한다.

(join을 사용할 수 있다)

 


.concat() 은 기준 열을 사용하지 않고 단순히 데이터를 연결(concatenate)한다.


출처: 데이터 사이언스 스쿨




3. Pandas 함수



예1) 데이터 분석용 함수

# sum, min, mean, var, ...

df[["키","나이"]].sum(axis=0) # axis = 0 : 행 | 1: 열


# corr(상관관계), cov(공분산) : 머신러닝에서 많이 사용되는 함수



예2) Na 처리하기

# Na값 대체하기 (최소값, 평균, 최대값,...)

age_min = df["나이"].min()

df["나이"] = df["나이"].fillna(value=age_min)


# Na값 제거하기

df=df.dropna(axis=0)



예3) 유용한 함수

# unique: 특정열을 중복없는 열로 만들어줌


# isin : 특정값 포함여부에 따른 Boolean 생성


# sort_index: 인덱스기반 정렬

df.sort_index(axis=0, ascending=False, by="키") # ascending=False 내림차순으로 정렬, by: 특정 열을 기준


# duplicated : 중복행 조회



추가)


pandas 데이터 타입은 총 3가지로


위에서 다룬


Series, DataFrame 이외에도


Panel(판넬)이라는 데이터 타입도 존재합니다. ( 단, Deprecated since version 0.20.0 )



오늘은 여기까지~


pandas가 손에 익으면 SQL보다 편하다네요~


여기서는 다루지 않았지만 pandas를 이용하여 다양한 방법으로 데이터를 로드할 수 있답니다!


csv, excel 등의 파일에서 데이터를 로드하는 부분은 제 이전의 포스팅을 보시면 굉장히 자주 등장합니다!



참고) numpy와 matplotlib은 이전 포스팅에서 다뤘답니다!


딥러닝에 필요한 파이썬 기본문법 | numpy & matplotlib



"백문이 불여일타!!"

반응형
반응형



안녕하세요~ 오늘은 드디어! 신경망에 대해 살짝 맛보도록 하겠습니다!



우선, 퍼셉트론과 신경망의 차이부터 알아봅시다!


퍼셉트론을 모른다면 "퍼셉트론(Perceptron)이란?" 을 참고하세요!



1. 퍼셉트론은 원하는 결과를 출력하도록 사람이 직접 가중치를 정해줘야 합니다!


AND, OR, NAND 게이트를 만들때 가중치를 채워 넣는 문제를 냈습니다!


어떻게 찾으셨나요? 저는 직접 숫자를 대입해보며 찾았답니다!


 혹시 더 쉽게 찾는 방법을 아시나요? 아신다면 댓글로 공유해주세요!



2. 신경망은 가중치 매개변수의 적절한 값을 기계가 데이터로부터 학습해서 자동으로 알아냅니다!





" 신경망 학습하기 "




이전 포스팅에서 신경망에 들어가는 함수


계단함수, 시그모이드 함수, 렐루 함수에 대해 알아보았습니다!



좀더 자세히 말하자면 위의 3가지 함수는


은닉층에 들어가는 함수 중 3가지를 의미합니다.




그렇다면 마지막 출력층에 들어가는 함수는 어떻게 될까요?


출력층 함수란,


그동안 흘러온 확률의 숫자를 취합해 결론을 내는 함수입니다.



신경망으로 구현하고자 하는 문제에 따라 사용하는 출력층 함수가 다릅니다.



1. 회귀(Regression)의 경우, 항등함수를 사용합니다.


항등함수란, 어떤 변수도 자기 자신을 함수값으로 하는 함수입니다.


[파이썬코드]

def identity(x): return x

간단하죠?




2. 분류(Classfication) 의 경우, 두 가지로 나뉘는데요.


2-1) 시그모이드(Sigmoid) 함수 : 2클래스 분류에서 사용합니다. ( ex, 개 vs 고양이 분류)


2-2) 소프트맥스(Softmax) 함수 : 다중 클래스 분류 (ex, 정상 폐사진 vs 폐결절, 폐혈증... 등 분류)



시그모이드는 은닉층의 활성화 함수에서 알아봤으니,



새로운 함수인, 소프트맥스 함수에 대해 더 자세히 알아보겠습니다.


소프트 맥스(Softmax) 함수란?


0과 1사이의 숫자를 출력하는 함수로, 출력하는 값은 확률입니다.


[파이썬 코드]


def softmax(a): C = np.max(a) exp_a = np.exp(a-C) sum_a = np.sum(exp_a) return exp_a / sum_a


[소프트 맥스 함수식]


e%203.10.png



소프트 맥스 함수식과 위의 파이썬 코드가 조금 다르죠?


그 이유는, overflow때문입니다!



우선, 소프트 맥스 함수는 지수함수를 사용하는데 이 지수함수라는 것은 아주 쉽게 아주 큰 값을 내뱉습니다.



예를 들어


exp == e (무리수: 자연상수)


e ^10 > 20000: 자연상수의 10승은 20000보다 크고


e ^1000 == inf : 자연상수의 1000승은 무한대(inf)를 나타냅니다.



따라서 표현할 수 없는 큰 값을 해결하기위해 아래와 같은 식으로 변형을 해서 사용합니다.




지수함수와 로그함수를 잘 모르겠다면 "여기"를 참고하세요!






" 이제, 아래의 신경망을 직접 구현해보도록 하겠습니다!"





import numpy as np # 신경망 함수 def sigmoid(x): return 1 / (1 + np.exp(-x)) def identity(x): return x def init_network(): network = {} network['W1'] = np.array([[1,3,5],[2, 4, 6]]) # weight 은 관습적으로 W라고 합니다. network['W2'] = np.array([[1,2],[3,4],[5,6]]) network['W3'] = np.array([[1,2],[3,4]]) return network

# 신경망 구현 def forward(network, x): W1, W2, W3 = network['W1'], network['W2'], network['W3'] y = np.dot(x, W1) y_hat = sigmoid(y) k = np.dot(y_hat, W2) k_hat = sigmoid(k) j = np.dot(k_hat, W3) j_hat = identity(j) # identity 대신 softmax함수를 사용할 수 있습니다. return j_hat network = init_network() x = np.array([1,2]) # 입력 y = forward(network, x) # 출력 print(y)





오늘은 여기까지!


신경망 학습 방법은 다음 포스팅에서 더 자세히 다루겠습니다!


좋은 하루 보내세요! 

반응형

+ Recent posts