CNN(합성곱 신경망)이란?
원본 이미지에 잘 설계된, 이미지의 특징을 찾기 위한 커널을 합성곱해서
내가 원하는, 커널에 의해 특징이 부각된 결과를 뽑아내는 것
필터를 인공지능이 자동으로 찾게 한다.
사람이 필터의 모양이 어떤 특징인지 해석 불가능하다.
필터의 특징맵이 최적의 결과를 만들어 내기 위한 과정이었다. 만을 추측가능하다.
즉, 원본 이미지가 있고, 이미지에 대한 행렬의 합성곱 연산을 하는 커널이 있다면,
필터 사이즈에 맞게 원본 이미지를 가져와서
픽셀값 곱하고 더하고... 한 칸씩 이동시키면서 필터와 원본 이미지를 접목해서
필터의 행렬을 다 계산해서 하나의 픽셀을 만든다.
커널이란?
합성곱 계층에서 가중치에 해당한다.
이미지의 특징을 찾기 위한 기능을 하는 행렬을 필터 또는 커널이라고 부른다.
필터의 특징을 역으로 이용하면,
어떤 사진만이 가지고 있는 이미지의 특징을 찾아내는 필터를 만들 수 있다.
CNN-MNIST... (28, 28) Grey 스케일
CNN-CIFAR-10...(32, 32, 3) RGB 스케일
Convolution(합성곱)
이미지 상에 어떤 특징이 어느 부분에 있는지를 알면 이미지를 분류할 때 유용
Convolution(합성곱)의 원리
필터를 순차적으로 사용자가 정한 이동량만큼 stride
Convolution 연산은 만들어질 때부터 3차원 형태의 데이터를 받음.
모델 생성에서 데이터의 형태가 (28, 28)이 아닌 (28, 28, 1)의 3차원 형태여야 한다.
따라서, 독립변수를 reshape 명령어를 통해 차원을 바꿔줘야 함
그리고, Conv2D(Convolutino)의 작성이 완료되어 Dense(완전 연결 계층, 전결합층)을 작성하기 전에 Flatten 명령어를 사용하여 입력 데이터를 1차원으로 바꿔주는 평탄화 작업을 수행해야 한다. 전결합층은 1차원을 입력으로 받기 때문
MaxPool2D
Pooling이란? 이미지 사이즈를 줄이는 것
2가지 방식이 있다.
1) max pool: 이미지 사이즈를 줄일 때 최대값을 남김
2) average pool: 이미지 사이즈를 줄일 때 평균값을 남김
-> Convolution처럼 겹치면서 하지 않고, 사용자가 정한 grid에서 원하는 값을 추출하여 이미지 크기를 줄임
겹쳐 이동하지 않고, 최대 혹은 평균값만 유지하며 옆으로 이동
완전 연결 계층의 한계와 CNN의 도입
완전 연결 계층은 2차원 이미지 데이터를 1차원 배열로 평탄화 시키는 과정에서 이미지 데이터의 형상이 훼손된다.
인접한 픽셀들 간의 중요한 정보가 손실되어, 글자의 크기, 위치, 회전, 변형에 민감하게 반응하지 못한다.
이 문제를 해결하기 위해 CNN이 제시되었으며,
CNN은 이러한 형상 변화를 고려하여 학습할 수 있다.
합성곱 계층
CNN의 핵심 구성 요소로, 데이터의 형상을 유지하면서 학습한다.
필터가 뉴런 역할을 하며, 학습 과정에서 적절한 필터가 업데이트된다.
필터는 이미지의 유사한 영역을 강조하는 특성 맵을 생성해 다음 계층으로 전달한다.
연산은 필터와 입력 데이터를 곱한 후 합을 구하는 방식으로 수행되며, 마지막에 편향이 더해진다.
패딩
출력 데이터의 공간적 크기를 조절하기 위해 사용되는 파라미터이다.
필터의 크기가 커질수록 특징 맵이 작아져 모서리 정보가 손실되기 때문에 이를 조절하기 위해 패딩을 적용한다.
입력 데이터와 출력 데이터의 크기를 같게 해주는 zero-padding, same-padding이 주로 사용된다.
스트라이드
입력 데이터에 필터를 적용할 때, 이동하는 간격을 조절하는 파라미터이다.
기본적으로 한 칸씩 이동하는 경우 스트라이드 값은 1이며,
입력 데이터가 너무 큰 경우 연산량을 줄이기 위해 스트라이드 값을 조정한다.
LeNet-5
import tensorflow as tf
import pandas as pd
# 테스트 데이터 무시. 반복을 돌 떄, 횟수를 가지고 오는 변수를 받지 않겠다.
(Xdata, Ydata), _ = tf.keras.datasets.mnist.load_data()
Xdata = Xdata.reshape(60000, 28, 28, 1) # CNN은 입력 데이터의 형태가 3차원이기 때문에 변환해줌
Ydata = pd.get_dumies(Ydata) # 원-핫 인코딩
X = tf.keras.layers.Input(shape=[28, 28, 1]) # 3차원 데이터 형태
H = tf.keras.layers.Conv2D(6, kernel_size=5, padding='same', activation='swish')(H)
# LeNet-5의 INPUT이 (32, 32)인데, mnist는 (28, 28)이기 때문에
# 코드 그대로 쓰려면 입력 데이터, 출력데이터의 크기를 같게 해주는 same-padding 사용해야함
# padding은, 출력 데이터의 공간적 크기를 조절하기 위해 사용하는 파라미터이다.
H = tf.keras.layers.MaxPool2D()(H) # 절반 줄어듦 (14, 14)가 됨
# 이미지 사이즈를 줄이는 것.
# Convolution 연산처럼 겹쳐 이동하지 않고, 사용자가 정한 grid에서 원하는 값 추출하여 이미지 크기를 줄인다.
H = tf.keras.layers.Conv2D(16, kernel_size=5, activation='swish')(H) # (14 - x) + 1 = 5.. 사이즈는 (10, 10)
H = tf.keras.layers.MaxPool2D()(H) # 절반 줄어듦 (5, 5)가 됨
H = tf.keras.layers.Flatten()(H) # CNN은 3차원을 입력 데이터로 받지만 Dense는 1차원 형태를 받아서 평탄화 해줌
H = tf.keras.layers.Dense(120, activation='swish')(H)
H = tf.keras.layers.Dense(84, activation='swish')(H)
Y = tf.keras.layers.Dense(10, activation='softmax')(H)
model = tf.keras.models.Model(X, Y)
model.compile(loss='categorical_crossentropy', metrics='accuracy')
# 모델 학습
model.fit(Xdata, Ydata, epochs=10)
# 모델 예측 및 정답 확인
pred = model.predict(Xdata[0:5])
print(pred.round(2))
Ydata[0:5]
RNN(순환 신경망)
연속된 데이터 형태에서 그 패턴을 찾아냄
가중치의 변화가 한 방향으로 이동하는 ANN과 달리,
RNN은 다시 자기 자신에게 돌아오는 것
일반적인 시퀀셜 모델은 입력 데이터가 은닉층을 거쳐 출력층에 전달되어 값이 계산된다.
동시에 다같이 계산했던 것을,
RNN은 이전 레이어의 한 뉴런으로부터 w 먼저 계산한 것을 가지고
그 값과 그 다음의 한 뉴런에 있는 w값을 포함하여 계산하고
그 값과 그 다음 한 뉴런에 있는 w값 계산하는 방식으로 계산 방법이 달라진다.
계산 방법이 달라지는 이유는
경우에 따라, w 잘못 계산되어 w값이 작아져 없어질 수 있는데,
이런 w값 한 번에 계산해서 넘어가면 중요 정보가 손실될 수 있다.
그래서 RNN은 각각의 정보가 다 중요하다고 판단하고 인공지능을 돌린다.
SimpleRNN(3, input_shape=(1, look_back)))
데스트셋
학습이 끝난 모델을 테스트 해보는 것
다른 데이터가 들어오면 오버피딩 되어 일반화 능력이 떨어질 수 있어서 테스트셋 사용
검증셋
최적의 학습 파라미터 찾기 위해 학습 과정에서 사용
검증셋 설정하면, 검증셋이 테스트한 결과를 추적하면서 최적의 모델을 만들 수 있다.
CallBack
학습이 진행되어도 테스트셋의 오차가 줄어들지 않으면 학습을 자동 종료시킴
EarlyStopping() 함수 사용
model.fit() 안에서 사용되며, 두 가지 파라미터가 있다.
monitor()
학습의 실행 결과 중 어떤 것 이용할 것인지 정함
patience()
지정한 값이 몇 번 이상 향상되지 않으면 종료할 것인지 정함
monitor='val_loss', patience=20
검증셋 오차가 20번 이상 낮아지지 않으면 학습을 조기 종료시킴(자동 중단)
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from sklearn.model_selection import train_test_spilt
from tensorflow.keras.callbacks import EarlyStopping
import pandas as pd
# 1. 데이터, 와인 데이터 로드
df = pd.read_csv('wine.csv', header=None)
# 와인의 속성을 X로, 와인의 분류를 y로 저장. (.iloc): 행번호로 선택하는 방법
X = df.iloc[:, 0:12]
y = df.iloc[:, 12]
# 학습셋과 테스트셋으로 나눔
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=True)
# 2. 모델 구조 설정
model = Sequential()
model.add(Dense(30, input_dim=12, activation='relu'))
model.add(Dense(12, ctivation='relu'))
model.add(Dense(8, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='bianry_crossentropy', optimizer='adam', metrics=['accuracy'])
# 3. 모델 학습
# 학습이 언제 자동 중단될지 설정
# 검증셋 오차(monitor='val_loss')가 20번 이상 낮아지지 않으면(patience), 검사 조기 종료
early_stopping_callback = EarlyStopping(monitor='val_loss', patience=20)
# 0.8 * 0.25 =0.2 0.2
history = model.fit(X_train, y_train, epochs=2000, batch_size=500, validation_spilt=0.25, verbose=1, callback=[early_stopping_callback])
# 조기 종료 사용.. 학습할 때 callback 함수 호출
자연어
우리가 평소에 말하는 음성이나 텍스트
자연어 처리
음성이나 텍스트를 컴퓨터가 인식하고 처리하는 것
컴퓨터 알고리즘은 수치로 된 데이터를 이해할 뿐, 텍스트는 이해할 수 없기 때문에
텍스트를 정제하는 전처리 과정이 필요하다.
토큰
입력될 데이터가 단어별, 문장별, 형태소별로 잘게 나누어진 하나의 단위
토큰화
텍스트를 잘게 나누는 과정
Word-Embedding
원-핫 인코딩을 그대로 사용하면 너무 길어진다는 단점이 있음
따라서 각 단어 간의 유사도를 계산해서 주어진 배열을 정해진 길이로 압축시키는 word embedding 사용한다.
word embedding으로 얻은 결과가 밀집된 정보를 가지고, 공간적 낭비가 적다.
Embedding(16, 4, input_length=2)
입력될 총 단어의 수는 16개. 16개의 토큰을 4개의 클래스로 유사도 계산해서 줄이겠다.
한 번에 입력되는 단어의 양은 2개씩 넣겠다.
embedding은 모델 설정의 맨 처음에 있어야 함
-> model = Sequential() 의 다음에..
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten, Embedding
from tensorflow.keras.utils import to_categorical
from numpy import array
# 1. 데이터 수집, 텍스트 리뷰 자료 지정, 긍정 리뷰는 1, 부정 리뷰는 0
docs = ["너무 재밌네요.", "최고예요", "참 잘 만든 영화예요.", "추천하고 싶은 영화입니다.", "한번 더 보고싶네요.",
"글쎄요.", "별로예요.", "생각보다 지루하네요.", "연기가 어색해요.", "재미없어요."]
classes = array([1, 1, 1, 1, 1, 0, 0, 0, 0, 0])
# 토큰화
token = Tokenizer()
token.fit_on_texts(docs)
print(token.word_index)
x = token.texts_to_sequences(docs)
print("\n리뷰 텍스트, 토큰화 결과: \n", x)
# 패딩
padded_x = pad_sequences(x, 4)
print("\n패딩 결과: \n", padded_x)
# 임베딩에 입력될 단어의 수
word_size = len(token.word_index) + 1
# 2. 모델 생성, word embedding 포함
model = Sequential()
model.add(Embedding(word_size, 8, input_length=4))
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 3. 학습
model.fit(padded_x, classes, epochs=20)
Padding
서로 다른 데이터의 길이를 맞추어 주는 것
pad_sequences(x, 4)
-> 독립변수가 4개이면 변수 4개로 맞춰줌
-> 서로 다른 길이의 데이터를 4로 맞춰줌
자연어 처리를 할 때는, 토큰의 개수가 문장마다 다 다르다.
이러한 경우 인공지능
으로
학습할 수 없기 때문에
입력받는거를, 데이터를 항상 길이를 똑같이 맞춰주는 패딩이 쓰인다.
원하는 길이보다 짧으면 0으로 채우고, 긴 데이터는 잘라서 길이를 맞춘다.
'IT' 카테고리의 다른 글
2-1 운영체제 (1) | 2024.11.07 |
---|---|
4차 산업혁명과 창의컴퓨팅 (2) | 2024.11.05 |
머신러닝 2nd (0) | 2024.10.20 |
머신러닝-1st (0) | 2024.10.20 |