출처 :
https://www.kaggle.com/shivamb/how-autoencoders-work-intro-and-usecases
https://www.kaggle.com/subinium/how-autoencoders-work-korean-ver
https://www.kaggle.com/swhan0329/korver-how-autoencoders-work-intro-and-usecases
1. Autoencoder
: 어떤 지도 없이도(즉, 레이블되어 있지 않은 훈련 데이터를 사용해서) 잠재표현(latent representation) 또는 코딩(일반적인 부호화)이라 부르는 입력 데이터의 밀집 표현을 학습할 수 있는 인공 신경망
- 일반적으로 입력보다 훨씬 낮은 차원을 가지므로 차원축소, 특히 시각화에 유용하다. (또한, 이미지 압축, 이미지 노이즈 제거, 이미지 생성, 특성 추출 등에도 쓰인다.)
- 일부 오토인코더는 훈련 데이터와 매우 비슷한 새로운 데이터를 생성할 수 있다. ⇒ 생성모델(generative model)
1.1 Autoencoder vs GAN
- 공통점 : 모두 비지도 학습, 밀집 표현을 학습, 생성모델로 사용
- 차이점 :
- 오토인코더는 단순히 입력을 출력으로 복사하는 방법을 배운다. 간단해보여도 다양한 방법을 통해 제약(ex. 입력에 잡음 추가)을 가하기 때문에 작업을 어렵게 만든다. 이런 제약으로 입력을 출력으로 바로 복사하지 못하고 데이터를 효율적으로 표현하는 방법을 배운다.
- GAN은 신경망 2개로 구성되어, 생성자(generator)는 훈련데이터와 비슷하게 보이는 데이터를 생성하는 반면 판별자(discriminator)s는 가짜 데이터와 진짜 데이터를 구별한다. 이 구조는 신경망이 훈련하는 동안 생성자와 판별자가 서로 경쟁하게 된다.(적대적 훈련)
1.2 Autoencoder 구성 요소
체스 플레이어처럼 오토인코더는 입력을 받아 패턴과 같은 효율적인 내부 표현으로 바꾸고 입력과 가장 가까운 어떤 것을 출력한다.
- 인코더(encoder) : 입력을 내부 표현으로 바꿈
- 디코더(decoder) : 내부 표현을 출력을 바꿈
- Latent View Representation : Latent view는 입력이 줄어들고 정보가 보존되는 가장 낮은 차원 공간을 나타낸다.
1.3 Autoencoder를 쓰는 이유
- 데이터 압축
- 차원의 저주 예방
- 중요한 Feature 찾기
1.4 How Autoencoder work
1차원 선형 데이터 매니폴드(실제 데이터가 존재하는 data representation space 내부의 공간)에 투영하여 각도 L을 없앰
from plotly.offline import init_notebook_mode, iplot
import plotly.graph_objs as go
import numpy as np
init_notebook_mode(connected=True)
## generate random data
N = 50
random_x = np.linspace(2, 10, N)
random_y1 = np.linspace(2, 10, N)
random_y2 = np.linspace(2, 10, N)
trace1 = go.Scatter(x = random_x, y=random_y1, mode="markers", name="Actual Data")
trace2 = go.Scatter(x = random_x, y= random_y2, mode="lines", name="Model")
layout = go.Layout(title="2D Data Repersentation Space", xaxis=dict(title="X2", range=(0,12)),
yaxis=dict(title="x1",range=(0,12)), height=400,
annotations=[dict(x=5, y=5, xref='x', yref='y', text='This 1D line is the DAta Manifold (where data resides)',
showarrow=True, align='center',arrowhead=2, arrowsize=1, arrowwidth=2, arrowcolor='#636363',
ax=-120, ay=-30, bordercolor='#c7c7c7', borderwidth=2, borderpad=4, bgcolor='orange',opacity=0.8)])
figure = go.Figure(data =[trace1], layout=layout)
iplot(figure)
- np.linspace(시작, 끝, 개수=50) : output은 array로, 특정 구간에서 출력할 데이터의 개수를 설정하여, 동일한 간격으로 숫자를 출력할 때 사용, 끝은 이하를 포함
- go.Layout 파라미터 : https://soohee410.github.io/plotly_annotation 참고
데이터를 표현하기 위해 2개의 차원(x축, y축)을 사용하지만, 다음과 같은 정보가 있으면 데이터를 하나의 차원으로 축소할 수 있다.
- 기준점 : A
- 수평선과의 각도 : L
위의 정보로 직선위의 점 B는 거리 D로 표현이 가능하다. (아래 참고)
random_y3 = [2 for i in range(100)]
random_y4 = random_y2 + 1
trace4 = go.Scatter(x = random_x[4:24], y = random_y4[4:300], mode="lines")
trace3 = go.Scatter(x = random_x, y = random_y3, mode="lines")
trace1 = go.Scatter(x = random_x, y = random_y1, mode="markers")
trace2 = go.Scatter(x = random_x, y = random_y2, mode="lines")
layout = go.Layout(xaxis=dict(title="x1",range=(0,12)),yaxis=dict(title="x2",range=(0,12)),height=400,
annotations=[dict(x=2, y=2, xref='x', yref='y', text='A', showarrow=True, align='center', arrowhead=2, arrowsize=1,
arrowwidth=2, arrowcolor='#636363', ax=20, ay=-30,
bordercolor='#c7c7c7', borderwidth=2,borderpad=4, bgcolor='orange',opacity=0.8),
dict(x=6, y=6, xref='x', yref='y', text='B', showarrow=True, align='center',
arrowhead=2,arrowsize=1, arrowwidth=2, arrowcolor='#636363', ax=20, ay=-30,
bordercolor='#c7c7c7',borderwidth=2, borderpad=4, bgcolor='yellow', opacity=0.8),
dict(x=2, y=2, xref='x', yref='y', text='angle L', ax=80, ay=-10)],
title="2D Data Representation Space", showlegend=False)
data = [trace1, trace2, trace3, trace4]
figure = go.Figure(data = data, layout = layout)
iplot(figure)
random_y3 = [2 for i in range(100)]
random_y4 = random_y2 + 1
trace4 = go.Scatter(x = random_x[4:24], y = random_y4[4:300], mode="lines")
trace3 = go.Scatter(x = random_x, y = random_y3, mode="lines")
trace1 = go.Scatter(x = random_x, y = random_y1, mode="markers")
trace2 = go.Scatter(x = random_x, y = random_y2, mode="lines")
layout = go.Layout(xaxis=dict(title="x1",range=(1.5,12)),yaxis=dict(title="x2",range=(1.5,12)),height=400,
annotations=[dict(x=2, y=2, xref='x', yref='y', text='A', showarrow=True, align='center', arrowhead=2, arrowsize=1,
arrowwidth=2, arrowcolor='#636363', ax=20, ay=-30,
bordercolor='#c7c7c7', borderwidth=2,borderpad=4, bgcolor='orange',opacity=0.8),
dict(x=6, y=6, xref='x', yref='y', text='B', showarrow=True, align='center',
arrowhead=2,arrowsize=1, arrowwidth=2, arrowcolor='#636363', ax=20, ay=-30,
bordercolor='#c7c7c7',borderwidth=2, borderpad=4, bgcolor='yellow', opacity=0.8),
dict(x=2, y=2, xref='x', yref='y', text='angle L', ax=80, ay=-10)],
title="2D Data Representation Space", showlegend=False)
data = [trace1, trace2, trace3, trace4]
figure = go.Figure(data = data, layout = layout)
iplot(figure)
hidden layer가 없는 autoencoder를 가정을 하고, B가 A와 L을 통해 표현될 수 있는지 알아보자.
입력 x1, x2는 낮은 표현인 d로 인코딩되고 x1, x2에 다시 투영(변환)된다.
① 잠재 공간에 점 표현
- Point A : (X1_A, X2_A)
- Point B : (X1_B, X2_B)
- A : (X1_A, X2_A) → (0,0)
- B : (X1_B, X2_B) → (u1_B, u2_B)
- u1_B = X1_B - X1_A, u2_B = X2_B - x2_A
② 거리 d와 각도 L로 점 표현
u1B와 u2B는 거리 d와 거리 L로 표현할 수 있다. 만약 각도 L만큼 기존 축으로 회전한다면, L은 0이 된다.
- (d,L) ⇒ (d,0)
- 이 데이터가 출력이 되고, 낮은 차원에서 표현한 입력 데이터이다.
- encoding
- (d, 0) = W * (u1B, u2B)
- W : 은닉층의 가중치 행렬
- decoding(인코딩 과정을 반대로 생각)
- (u1B, u2B) = Inverse(W) * (d, 0)
신경망은 어떻게 해결해야 할까?
직관적으로 생각해보면, 매니폴드공간(manifold space)에서 심층 신경망은 선형 데이터 폴드 뷰를 얻기 위해 공간을 구부리는 속성을 가지고 있다. autoencoder 구조는 hidden layer에 이 속성을 적용하여 latent view space에서 낮은 수준의 표현을 학습할 수 있다.
2. Implementation
2.1 UseCase 1 : Image Reconstruction
2.1.1 필요한 library를 불러온다.
from keras.layers import Dense, Input, Conv2D, LSTM, MaxPool2D, UpSampling2D
from sklearn.model_selection import train_test_split
from keras.callbacks import EarlyStopping
from tensorflow.keras.utils import to_categorical
from numpy import argmax, array_equal
import matplotlib.pyplot as plt
from keras.models import Model
from imgaug import augmenters
from random import randint
import pandas as pd
import numpy as np
- array_equal : 두 array를 비교할 때 사용, array 형태와 요소들이 동일할 경우 True를 반환
- imgaug : 이미지를 augmentation 해주는 라이브러리
2.1.2 Dataset Prepration
데이터셋을 불러오고, 예측값과 타겟을 분리하며 입력데이터를 정규화한다.
# read dataset
train = pd.read_csv('../data/fashion-mnist_train.csv')
train_x = train[list(train.columns)[1:]].values
train_y = train['label'].values
# normalize and reshape the predictors
train_x = train_x / 255
# create train and validation datasets
train_x, val_x, train_y, val_y = train_test_split(train_x, train_y, test_size=0.2)
# reshape the inputs
train_x = train_x.reshape(-1, 784)
val_x = val_x.reshape(-1, 784)
- train_x의 최소값이 0, 최대값이 255이므로 train_x에 255를 나눠서 정규화한다.
2.1.3 Create Autoencoder architecture
인코딩 구조는 각각 1500, 1000, 500 노드로 3개의 layer로 구성되어 잠재 공간에 10개의 노드로 연결한다. 그리고 이 10개는 다시 각각 500 , 1000, 1500개의 노드로 구성된 3개의 디코딩 구조로 연결된다. 최종 계층은 입력 계층과 같은 수의 노드로 구성한다.
## input layer
input_layer = Input(shape=(784,))
## encoding architecture
encode_layer1 = Dense(1500, activation='relu')(input_layer)
encode_layer2 = Dense(1000, activation='relu')(encode_layer1)
encode_layer3 = Dense(500, activation='relu')(encode_layer2)
## latent view
latent_view = Dense(10, activation='sigmoid')(encode_layer3)
## decoding architecture
decode_layer1 = Dense(500, activation='relu')(latent_view)
decode_layer2 = Dense(1000, activation='relu')(decode_layer1)
decode_layer3 = Dense(1500, activation='relu')(decode_layer2)
## output layer
output_layer = Dense(784)(decode_layer3)
model = Model(input_layer, output_layer)
요약정보를 통해 모델을 확인해보자
model.summary()
조기 학습 종료를 이용해 훈련을 해보자
model.compile(optimizer='adam', loss='mse')
early_stopping = EarlyStopping(monitor='val_loss', min_delta=0, patience=10, verbose=1, mode='auto')
model.fit(train_x, train_x, epochs=20, batch_size=2048, validation_data=(val_x, val_x), callbacks=[early_stopping])
검증 데이터에 대한 예측을 생성해보자
preds = model.predict(val_x)
2.1.4 원본 이미지와 예측이미지를 시각화
1) Inputs : Actual Images
## 원본 이미지
from PIL import Image
f, ax = plt.subplots(1,5)
f.set_size_inches(80, 40)
for i in range(5):
ax[i].imshow(val_x[i].reshape(28,28))
plt.show()
- from PIL : Pillow 패키지에서 가장 중요한 클래스는 이미지를 표현하는 Image 클래스
2) Predicted : Autoencoder Output
## 예측 이미지
f, ax = plt.subplots(1,5)
f.set_size_inches(80, 40)
for i in range(5):
ax[i].imshow(preds[i].reshape(28,28))
plt.show()
위와 같이 나오는 이유를 모르겠다... 예측이 잘 안된 것 같은데
2.2 UseCase 2 : Image Denoising
2.2.1 Noisy Images
이미지에 노이즈를 추가하여 만들 수 있는데, 노이즈 종류는 다음과 같다.
- Salt and Pepper Noise
- Guassian Noise
- Periodic Noise
- Speckle Noise
여기서는 Salt and Pepper Noise를 사용했다. Salt and Pepper Noise란 Impulse Noise(0또는 255의 픽셀 값과 같이 뚜렷하게 잘못된 밝기 값을 가지는 noise를 의미)에 포함된 Noise로 영상 내에서 검은색 혹은 흰색 점의 형태로 발생하는 noise이다.
2.2.2 recreate, normalize, reshape
## recreate the train_x array and val_x array
train_x = train[list(train.columns)[1:]].values
train_x, val_x = train_test_split(train_x, test_size = 0.2)
## normalize and reshape
train_x = train_x / 255
val_x = val_x/255
train_x = train_x.reshape(-1,28,28,1)
val_x = val_x.reshape(-1,28,28,1)
이후에 이미지 입력에 대해 잘 작동할 수 있는 convolutional layer를 추가할 예쩡이다. 그래서 입력 데이터를 convolutional network에 넣기 위해 shape를 28*28 matrix로 바꿔준다.
# lets add sample noise - salt and pepper
noise = augmenters.SaltAndPepper(0.1)
seq_object = augmenters.Sequential([noise])
train_x_n = seq_object.augment_images(train_x * 255)/255
val_x_n = seq_object.augment_images(val_x * 255)/255
▶ 노이즈 추가 전 이미지
f, ax = plt.subplots(1,5)
f.set_size_inches(80,40)
for i in range(5,10):
ax[i-5].imshow(train_x[i].reshape(28,28))
plt.show()
▶ 노이즈 추가 후
f, ax = plt.subplots(1,5)
f.set_size_inches(80,40)
for i in range(5,10):
ax[i-5].imshow(train_x_n[i].reshape(28,28))
plt.show()
2.2.3 모델 생성
# input layer
input_layer = Input(shape=(28,28,1))
# encoding architecture
encoded_layer1 = Conv2D(64,(3,3),activation='relu', padding='same')(input_layer)
encoded_layer1 = MaxPool2D((2,2), padding='same')(encoded_layer1)
encoded_layer2 = Conv2D(32, (3,3), activation='relu', padding='same')(encoded_layer1)
encoded_layer2 = MaxPool2D((2,2), padding='same')(encoded_layer2)
encoded_layer3 = Conv2D(16, (3,3), activation='relu',padding='same')(encoded_layer2)
latent_view = MaxPool2D((2,2),padding='same')(encoded_layer3)
# decoding architecture
decoded_layer1 = Conv2D(16, (3,3), activation='relu', padding='same')(latent_view)
decoded_layer1 = UpSampling2D((2,2))(decoded_layer1)
decoded_layer2 = Conv2D(32, (3,3), activation='relu', padding='same')(decoded_layer1)
decoded_layer2 = UpSampling2D((2,2))(decoded_layer2)
decoded_layer3 = Conv2D(64, (3,3), activation='relu')(decoded_layer2)
decoded_layer3 = UpSampling2D((2,2))(decoded_layer3)
output_layer = Conv2D(1,(3,3),padding='same')(decoded_layer3)
# compile the model
model_2 = Model(input_layer, output_layer)
model_2.compile(optimizer='adam', loss='mse')
▶ Encoding Architecture
▷ 3개의 Convolutional Layer와 3개의 Max Pooling Layer를 쌓아서 구성한다.
▷ padding='same'으로 이미지 크기를 패딩을 통해 유지된다.
▷ Max pooling layer는 이미지 차원을 다운 샘플링 하기 위해 사용한다. 초기 표현의 겹치지 않는 부분 영역에 최대 필터를 적용한다.
▶ Decoding Architecture
▷ 거의 유사하게 Convolutional Layer를 3개 사용한다. 그렇지만 Max Pooling 대신 Upsampling layer를 이용한다.
▷ UpSampling은 입력 벡터를 더 높은 차원으로 업샘플링하기 위해 사용한다.
2.2.4 모델 요약 정보
model_2.summary()
2.2.5 조기 학습 종료로 학습
early_stopping = EarlyStopping(monitor='val_loss', min_delta=0, patience=10, verbose=5, mode='auto')
history = model_2.fit(train_x_n, train_x, epochs=20, batch_size=2048, validation_data=(val_x_n, val_x), callbacks=[early_stopping])
2.2.6 시각화
▶ 노이즈 적용된 검증 데이터
f, ax = plt.subplots(1,5)
f.set_size_inches(80, 40)
for i in range(5,10):
ax[i-5].imshow(val_x_n[i].reshape(28, 28))
plt.show()
▶ 노이즈를 없앤 오토인코딩 이후 검증 데이터
preds = model_2.predict(val_x_n[:10])
f, ax = plt.subplots(1,5)
f.set_size_inches(80, 40)
for i in range(5,10):
ax[i-5].imshow(preds[i].reshape(28, 28))
plt.show()
2.3 UseCase 3 : Sequence to Sequence Prediction using AutoEncoders
앞의 예시에서는 기본적으로 2차원 데이터였으나, 이번 시퀀스 데이터(ex. 시계열 데이터, 문자열 데이터)는 1차원 데이터이다.
2.3.1 Autoencoder Architecutre
1) LSTM의 작동 방식
- LSTM(Long Short-Term Memory)은 내부 루프로 구성된 반복적 신경망이다.(RNN)
- 다른 RNN과 달리 네트워크의 내부 게이트를 사용하면 시간에 따른 역전파 또는 BPTT(Back Propagation Through Time)를 활용하여 성공적으로 훈련하고, 기울기 소실 문제를 방지할 수 있다.
- LSTM layer에서 메모리 단위의 수를 정의할 수 있다. 계층 내의 각 단위 또는 셀은 내부 메모리/셀 상태(c)를 가지며 종종 h라는 표현으로 숨겨진 상태를 출력한다.
- Keras를 사용하면 LSTM 계층의 출력 상태와 LSTM 계층의 현재 산태에 모두 액세스할 수 있다.
2) Autoencoder 구조
: LSTM layer로 구성된 시퀀스를 학습하고 생성
- 인코더 구조 : 시퀀스를 입력으로 사용하고 LSTM의 현재 상태를 출력으로 반환
- 디코더 구조 : 시퀀스 및 인코더 LSTM 상태를 입력으로 사용하고 디코딩된 출력 시퀀스를 반환
2.3.2 고정 길이의 무작위 시퀀스를 포함하는 시퀀스 데이터 세트 생성
▶ 무작위 시퀀스를 생성하는 함수를 정의
▷ X1 : 난수를 포함하는 입력 시퀀스
▷ X2 : 시퀀스의 다른 요소를 재현하기 위해 seed로 사용되는 패딩된 시퀀스를 나타냄
▷ y : 타켓 시퀀스 또는 실제 시퀀스
def dataset_preparation(n_in, n_out, n_unique, n_samples):
X1, X2, y = [], [], []
for _ in range(n_samples):
## input : create random numbers sequence
inp_seq = [randint(1, n_unique - 1) for _ in range(n_in)]
## create target sequence
target = inp_seq[:n_out]
## create padded sequence / seed sequence
target_seq = list(reversed(target))
seed_seq = [0] + target_seq[:-1]
# convert the elements to categorical using keras api
X1.append(to_categorical([inp_seq], num_classes = n_unique))
X2.append(to_categorical([seed_seq], num_classes = n_unique))
y.append(to_categorical([target_seq], num_classes = n_unique))
# remove unnecessary dimention
X1 = np.squeeze(np.array(X1), axis=1)
X2 = np.squeeze(np.array(X2), axis=1)
y = np.squeeze(np.array(y), axis=1)
return X1, X2, y
▶ reversed
▷ 파이썬의 내장함수 = list에서 제공해주는 함수
▷ iterator의 요소를 역순으로 리턴
▶ np.squeeze(배열, 축)
▷ 축의 차원을 축소
samples = 1000000
features = 51
inp_size = 6
out_size = 3
inputs, seeds, outputs = dataset_preparation(inp_size, out_size, features, samples)
print("Shapes: ", inputs.shape, seeds.shape, outputs.shape)
print("Here is first categorically encoded input sequence looks like: ",)
inputs[0][0]
2.3.3 모델 생성
def define_models(n_input, n_output):
## define the encoder architecture
## input : sequence
## output : encoder states
encoder_inputs = Input(shape=(None, n_input))
encoder = LSTM(128, return_state=True)
encoder_outputs, state_h, state_c = encoder(encoder_inputs)
encoder_states = [state_h, state_c]
## define the encoder-decoder architecture
## input : a seed seqeunce
## output : decoder states, decoded output
decoder_inputs = Input(shape=(None, n_output))
decoder_lstm = LSTM(128, return_sequences=True, return_state=True)
decoder_outputs, _, _ = decoder_lstm(decoder_inputs, initial_state=encoder_states)
decoder_dense = Dense(n_output, activation='softmax')
decoder_outputs = decoder_dense(decoder_outputs)
model = Model([encoder_inputs, decoder_inputs], decoder_outputs)
## define the decoder model
## input : current states + encoded sequence
## output : decoded sequence
encoder_model = Model(encoder_inputs, encoder_states)
decoder_state_input_h = Input(shape=(128,))
decoder_state_input_c = Input(shape=(128,))
decoder_states_inputs = [decoder_state_input_h, decoder_state_input_c]
decoder_outputs, state_h, state_c = decoder_lstm(decoder_inputs, initial_state=decoder_states_inputs)
decoder_states = [state_h, state_c]
decoder_outputs = decoder_dense(decoder_outputs)
decoder_model = Model([decoder_inputs] + decoder_states_inputs, [decoder_outputs] + decoder_states)
return model, encoder_model, decoder_model
▶ LSTM
▷ 신경망이 장기적인 관계를 학습하기 위해 중요한 정보를 확실하게 전송할 목적으로 설계되었다.
▷ LSTM(units, return_sequences)
▷ units: 양의 정수, 아웃풋 공간의 차원
▷ return_sequences: 불리언. 아웃풋 시퀀스의 마지막 아웃풋을 반환할지, 혹은 시퀀스 전체를 반환할지 여부
ex. (64, 100, 65) # (batch_size, sequence_length, vocab_size)
- True : (64, 100, 65)
- False : (64, 65), 마지막 output만 반환되기 때문 즉, 100자의 모든 시퀀스에 대해 마지막 예측 문자만 반환
2.3.4 모델 구조
autoencoder, encoder_model, decoder_model = define_models(features, features)
▶ Encoder
encoder_model.summary()
▶ Decoder
decoder_model.summary()
▶ Autoencoder
autoencoder.summary()
2.3.5 autoencoder 모델 학습
autoencoder.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['acc'])
autoencoder.fit([inputs, seeds], outputs, epochs=1)
2.3.6 시퀀스 예측
def reverse_onehot(encoded_seq):
return [argmax(vector) for vector in encoded_seq]
def predict_sequence(encoder, decoder, sequence):
output = []
target_seq = np.array([0.0 for _ in range(features)])
target_seq = target_seq.reshape(1,1,features)
current_state = encoder.predict(sequence)
for t in range(out_size):
pred, h, c = decoder.predict([target_seq] + current_state)
output.append(pred[0,0,:])
current_state = [h,c]
target_seq = pred
return np.array(output)
for k in range(5):
X1, X2, y = dataset_preparation(inp_size, out_size, features, 1)
target = predict_sequence(encoder_model, decoder_model, X1)
print('\nInput Sequence=%s SeedSequence=%s, PredictedSequence=%s' %(reverse_onehot(X1[0]), reverse_onehot(y[0]), reverse_onehot(target)))
참고자료
1. Autoencoder
- 핸즈온 머신러닝 : 사이킷런, 케라스, 텐서플로 2를 활용한 머신러닝, 딥러닝 완벽 실무
- https://analysisbugs.tistory.com/56
2. np.linspace https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=jjys9047&logNo=221565200268
3. plotly annotation https://soohee410.github.io/plotly_annotation
4. array_equal https://codetorial.net/tips_and_examples/compare_two_lists.html
5. imgaug https://uos-deep-learning.tistory.com/17
7. Noise https://m.blog.naver.com/PostView.nhn?isHttpsRedirect=true&blogId=laonple&logNo=220811027599
8. reversed https://www.zehye.kr/python/2019/11/21/11python_reverse_reversed/
9. LSTM
▷ https://dgkim5360.tistory.com/entry/understanding-long-short-term-memory-lstm-kr ★추천★
'데이터 분석 > kaggle' 카테고리의 다른 글
[kaggle] Fruits 360 (0) | 2021.08.28 |
---|---|
[kaggle] image classification 필사 목록 (0) | 2021.08.25 |
[kaggle] Statoil/C-CORE Iceberg Classifier Challenge(수정중) (0) | 2021.08.25 |
댓글