반응형

CNN (Convolutional Neural Network)

  • CNN은 최소한의 전처리(preprocess)를 사용하도록 설계된 다계층 퍼셉트론의 한 종류이다.
  • CNN은 하나 또는 여러개의 합성곱 계층과 그 위에 올려진 일반적인 인공 신경망 계층들로 이루어져 있으며, 가중치와 통합 계층(pooling layer)들을 추가로 활용한다.
  • DNN에서는 Dense Layer를 사용한다. → Dense Layer는 Wx+b이라서 Linear와 Rogistic 회귀가 합쳐진 느낌
  • CNN에서는 Convolution이라는 연산을 활용함
퍼셉트론 관련 포스팅 [AI] 딥러닝의 개요 - 퍼셉트론
DNN 관련 포스팅 [AI] DNN(Deep Neural Network)의 이해 및 실습

 

합성곱 (Convolution)

  • 원래는 필터가 정해져 있고 필터를 거쳐서 나오는 것을 특징으로 활용해서 기존에 머신러닝에서 feature 추출하는 방향으로 사용을 했었는데 딥러닝에서 넘어오면서 Convolution에서 필터 자체도 학습하도록 메커니즘이 생김

  • 필터와 실제 이미지를 겹쳐서 각자 곱한 다음에 9개를 다 더해서 값이 나옴
    → W1*1 + W2*1 + W3*1 + W4*0 + W5*1 + W6*1 + W7*0 + W8*0 + W9*1
  • 기존에는 필터를 미리 정의를 해놓고 곱해서 특징을 뽑았었는데, 딥러닝에서는 필터도 학습을 함

 

원래 필터는 0과 1만 있는 게 아니라 여러 숫자가 나올 수 있고, 소수로 되어있음

 

합성곱 padding

  • Convolution을 하면 사이즈가 작아지는 현상이 발생할 수 있다.
    → 맨 외곽에 padding을 넣어주면 필터가 외곽에서 부터 시작을 하게 되는데 그럼 기존과 크기가 똑같아진다.
  • 이미지 크기를 조절하기 위해 사용한다.
  • 이미지 외곽에 어떤 것이 있는지 인식하는 학습 효과도 있음
  • padding은 기본적으로 0으로 만든다.

 

Pooling

  • Convolution layer의 출력을 입력으로 받아서 크기를 줄이거나 특정 데이터 강조
  • 이미지의 크기가 너무 크다보니 데이터를 그대로 사용하기엔 파라미터가 너무 커지고 연산도 오래걸려서 Pooling 사용으로 크기를 줄여줌
  • 학습하는 파라미터가 존재하지 않음! Convolution Layer는 학습 파라미터 존재
  • Max Pooling
    • 윈도우에서 제일 큰 값을 가지고 오는 Pooling
  • Average Pooling
    • 윈도우에서 평균 값을 가지고 오는 Pooling

→ 몇 칸 움질일지 정할 수 있고, 윈도우 사이즈(2*2)도 정할 수 있음

→ 조금씩 움직이면 더 세밀하게 되는데 차원이 커지고 연산이 많아져서 성능에는 유리할 수 있지만 속도가 느려짐

 

Pooling을 사용하면 속도가 빨라지는데 학습 속도도 빨라지고 서비스할 때 추론 속도도 빨라지게 되는데 Pooling을 많이 사용하게 되면 데이터를 없애는 것이기 때문에 데이터 손실이 일어날 수 있어서 성능에 오히려 악영향을 줄 수 있음

 

반응형

 

손글씨 데이터를 가지고 만든 CNN 구성

  • kernel = filter (55 필터 적용) → 학습해야하는 파라미터 수 : 55 = 25개 + b값 = 50개 * 채널갯수
  • channels : 필터가 여러개 → padding을 안하면 크기가 줄어든다.
  • Convolution Layer → Pooling Layer → Convolution Layer → Pooling Layer → Flattened → (dropout) → softmax Layer
    • Flattened → Dense를 하기 위해서 Flatten을 해줘야함, 1열로 세워져야 Dense가 입력으로 들어갈수 있어서 Flatten을 해줌
    • Convolution, Pooling Layer ⇒ Feature Extaction (특징 추출)
    • Fully-Connected ⇒ Classification (분류)

Convolution Layer가 의미하는게 무엇인가?? 특징을 추출하는 부분

 

CNN 실습

import tensorflow as tf

# data download
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

 

  • 이미지의 경우, 위의 코드처럼 쓰면 2차원으로 받아오는데 실제로는 3차원이 Convolution Layer에 들어가야해서 데이터를 바꿔줘야함
    • 28*28에 대한 60000개의 데이터가 x_train에 들어있어서 원래는 3차원이 들어가있는데 4차원으로 바꿔줘야함
    • Convolution을 할 때는 지금은 흑백이라서 채널이 한개짜린데 원래 이미지는 RGB 채널을 가지기때문에 채널이 기본적으로 3개가 있음! 그렇기 때문에 이미지의 input은 3차원이 들어가야하므로 reshape를 해줘야 학습이 됨
      → 2828 의 이미지에 채널 1개를 곱해서 (28*28*1) - 3차원
    • reshape : 모양을 변경하는 함수 → 기존과 바뀐 것의 데이터 총 사이즈는 같아야함
x_train = x_train.reshape((60000, 28, 28, 1)) # 60000만개의 학습 데이터
x_test = x_test.reshape((10000, 28, 28, 1))

 

원래 이미지는 RGB로 되있기 때문에 3차원인데 손글씨는 2차원이기때문에 3차원으로 변경을 해준것이다!!

그런데 Conv2D를 쓰는 이유는?
어쨋든 convolution 자체는 Convolutin 필터 사이즈가 2차원이기때문에!! 2차원으로만 컨볼루션 연산을 하기 때문에 Conv2D 함수를 쓰는거임

 

  • 모델 정의
    • Conv2D : convolution 2D 이미지를 사용
      → 32 : 채널갯수 , (5, 5) : 필터 사이즈
      → 처음에는 input_shape를 지정해줘야함
    • MaxPooling2D : 2*2 윈도우 사이즈
    • 채널갯수, hidden Layer 갯수는 임의로 넣은 값임
#model define
model = tf.keras.models.Sequential()

model.add(tf.keras.layers.Conv2D(32, (5, 5), activation='relu', input_shape=(28,28,1)))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(64, (5, 5), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))

model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='softmax'))
model.summary()

 

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

model.fit(x_train, y_train, epochs=10)

 

model.evaluate(x_test, y_test, verbose=2)

 

 

반응형

'AI > 이미지인식' 카테고리의 다른 글

[AI] Image Classification과 Backbone의 이해  (0) 2022.06.08
반응형

DNN (Deep Neural Network)

  • DNN은 입력층(input layer)과 출력층(output layer) 사이에 여러 개의 은닉층(hidden layer)들로 이뤄진 인공신경망(Artificial Neural Network, ANN)이다.
  • input에 대해서 ouput까지 Layer를 거치돼, input Layer 다음에 W랑 b가 있어서 Wx+b를 거치게 되고 hidden layer1 에서는 활성화 함수가 있다고 보면 된다.
  • 그 후 다시 Wx + b를 거치고 활성화 함수를 거친 후, output layer가 만약 분류였다면 마지막에는 softmax를 activation function(활성화 함수)을 활용한다.

 

DNN 실습

  • XOR 실습이랑 거의 비슷함
  • tensorflow import
import tensorflow as tf

tf.__version__ #tensorflow library version check
# 2.3.0 version

 

  • tensorflow에서 제공하는 데이터 활용
    • mnist라는 데이터 불러올 수 있음
    • http://yann.lecun.com/exdb/mnist/ → 여기에서 공개된 mnist dataset
    • 0부터 9까지 10개에 대한 손글씨 데이터임 → 이미지 크기는 28 x 28 (흑백이라서 채널도 하나뿐)
    • 여기서 학습 set과 test set을 나눠서 제공하기 때문에 학습 set 따로 test set 따로 받음
    • x는 이미지 실제 값
# data download
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()

 

  • 실제 들어있는 값 확인 (x_train, y_train)

→ 실제로 들어있는 값 확인 가능하다. (한 줄에 28개씩 28 줄! 이렇게 데이터가 숫자로 들어감)

→ uint8 (unsigned int 8) 데이터 꼴로 들어가 있음

 

 

→ y_train 에는 5가 들어있음

→ 5번의 숫자에 대한 이미지가 x_train에 들어있음

 

 

 

  • 이미지를 분류하는 모델 생성 (XOR-2 모델과 비교)
    • XOR 모델에서는 애초에 1줄짜리 리스트가 들어있어서 shape=2 해주고 input을 넣어주면 되는데, 지금은 2차원 데이터가 들어있어서 Dense Layer 앞에서 1차원으로 되어 있어야만 들어갈 수 있는 문제가 있어서 Flatten을 해주면 input이 됨
      Flatten : 2D 이미지를 1D로 바꾸기 위해 사용
    • tf.keras.layers.Dense(128, activation='relu')
      → 위에 실제 학습할 파라미터가 들어있음
    • Dropout : 0.2는 노드를 비활성화 시킬 비율
    • softmax : 0부터 9까지 10개기 때문에 softmax를 10개로 지정해줌
#model define
model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape=(28,28)), # Flatten: 2d image -> 1d
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dropout(0.2), # dropout -> to reduce overfitting problem
    tf.keras.layers.Dense(10, activation='softmax')
])

# XOR-2 모델
# model = tf.keras.Sequential([
#      tf.keras.layers.Input(shape=2, dtype='float32'),
#      tf.keras.layers.Dense(4, activation='relu'),
#      tf.keras.layers.Dense(4, activation='relu'),
#      tf.keras.layers.Dense(2, activation='softmax')
# ])
반응형

Dropout 설명

기본 딥러닝
Dropout

 

→ Dropout 은 일부 노드를 끊어준다.

→ 일부 노드를 끊어주면 Overfitting될 확률이 낮아진다.

→ Dropout도 epochs 돌때마다 비활성화되는 노드들이 바뀌기 때문에 Dropout을 적용하게 되면 머신러닝에서 나왔던 Overfitting 과적합 문제가 많이 줄어든다.

Dropout은 Overfitting 과적합 문제를 줄이기 위해서 사용

 

 

  • 모델의 파라미터 개수 확인
model.summary() # 784(input_size)*128(w) + 128(b) = 100480

→ 입력 개수 x(784) * W(128) + b(128) = 100480

→ shape 하나당 b가 하나 있기 때문에 128을 더해줌

→ 입력 개수 x(128) * W(10) + b(10) = 1290

 

 

  • model.compile : 모델을 학습할 때 어떤 방식을 사용할지 정해주는 함수
    • loss='sparse_categorical_crossentropy' → cross enttopy인데 분류를 여러 개로 할 때 사용
    • metrics=['accuracy'] → 정확도를 보겠다는 것
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

 

  • 학습
    • fit() 함수를 호출할 때 추가적으로 넣을 수 있는 게 많다 (https://keras.io/ko/models/sequential/ 참고)
    • shuffle : 불리언 (각 세대를 시작하기 전 학습 데이터를 뒤섞을지 여부) 혹은 ('batch'에 넣을) 문자열
    • use_multiprocessing : 병렬 처리 관련?
model.fit(x_train, y_train, epochs=10)

→ 90점 넘게 분류가 나옴

 

 

  • 평가
    • test 데이터가 따로 있기 때문에 test 데이터를 넣어서 몇 점이 나오는지 출력
    • verbose : 어떤 방법으로 출력할지
model.evaluate(x_test, y_test, verbose=2)

→ 평가는 testset에서 94점이 나온다.

반응형
반응형

순전파 (Forword Propagation)

  • Input에서부터 Output이 나올때까지 순서대로 계산을 하는 과정
  • loss를 구하려면 실제값이랑 Output (H(x))의 차이를 알아야 한다.
  • loss를 구할 수 있다
  • 모델을 론칭을 하면 학습은 안하고 추론(예측)만 함 → 모델 추론

 

 

역전파 (Back Propagation)

  • 딥러닝에서 제일 중요한 개념★
  • 학습하는 과정에서만 사용된다.
  • 순전파와 반대로 출력층에서 입력층 방향으로 계산하면서 가중치를 업데이트 한다.
왜 반대로 가는가??
학습을 할 때 가중치를 업데이트를 하는데 만약 순전파라면 Input에서 wieght를 바꾸고 바꾼 wieght를 Hidden Layer에서 또 바꾸고 Output에서 또 바꾸는데 그러면 Output에서 loss 차이가 너무 많이 날 수 있음 !!
→ loss를 Output에서 구하는데 Input에서부터 바꾸게 되면 Hidden Layer에서 가중치를 업데이트하기 위해서는 옵티마이저를 학습하는 과정에서 미분이 있는데 그 다음층 (Output)에 미분결과가 필요한데 그 다음층 미분 결과를 알 수가 없기 때문에 순방향으로는 가중치 업데이트를 못함 !!!
→ 이 문제를 해결하기 위해 위에서부터 가중치를 미분을 해서 업데이트한 후 그 값이 그대로 내려가서 또 업데이트 하고 업데이트 하면서 가중치를 반대방향으로 업데이트를 하는 아이디어를 고안해내서 역전파가 생김
→ 층이 아무리 깊어져도 학습을 할 수 있다.
  • Gradient Descent를 활용하여 학습을 할 경우, 다음 층의 미분값이 필요하게 되는데, 현재 층에 연산이 끝나지 않아서 다음 층의 미분 값을 알 수가 없는 문제를 해결하기 위해 나옴

 

 

활성화 함수

활성화 함수 (activation function)

  • 뉴런에서 출력값을 결정하는 함수
  • 실제 뇌를 구성하는 신경 세포 뉴런이 전위가 일정치 이상이 되면 시냅스가 서로 화학적으로 연결되는 모습을 모방한 함수
    (좀 더 풀어서 설명) 실제 뇌에서는 뉴런이 전위(전기신호)에서 일정 세기 이상이 되면 시냅스가 서로 연결되면서 1이라고 하고, 아닌 경우 0이라고 하는걸 모방을 한다.
  • 만약 선형함수라면?? Wx라고 가정을 한다면 결국 층을 세번을 거치면 아래 수식처럼 나오고 그럼 W의 세제곱짜리 층 한개가 있는 거랑 W짜리 층 세개 있는거랑 똑같은 결과가 나와기때문에 층을 아무리 쌓아도 의미가 없어지기 때문에 선형함수는 사용 불가능하다.
    → 반드시 비선형 함수를 사용해야함

아무리 은닉층을 추가해도, 선형함수는 Weight만 곱해지는 효과라서 그럼 층이 세개일때는 세제곱으로 Weight가 가지고 있는 층 하나로 대체 가능하기 때문에 결국에는 의미가 없어져서 선형함수로는 활성화 함수를 쓸 수 없음

 

계단함수 (Step Function)

  • 제일 기본적이고, 실제로는 전혀 사용하지는 않음
  • 0보다 클 때는 1 , 0보다 작을 때는 0
  • 선이 하나는 아니기 때문에 비선형 함수이다.

반응형

시그모이드 함수(Sigmoid Function)

  • logistic regression 에서 활용했던 함수
  • 시그모이드 함수 하나만 쓰면 결국 로지스틱 회귀랑 똑같은게 된다.
    → 층 하나에 그 층에서 시그모이드 함수만 활성화 함수로 쓰게 된다면 로지스틱 회귀랑 똑같아지는 효과
XOR-1 실습 때(바로 전 포스팅), 층 하나만 놓고 시그모이드를 작성을 해서 모델에 넣었는데 그게 바로 로지스틱 회귀이다. 
시그모이드 함수를 여러개 쌓으면 로지스틱 회귀를 여러개 쌓은것이 됨 (그래서 중요)

  • 활성화 함수가 거치기 직전까지가 선형함수라고 생각하면 됨
    → 퍼셉트론에서 Wx + b 가 활성화 함수를 거치면서 시그모이드로 바껴서 로지스틱 회귀처럼 그래프가 바뀌는 것 때문에 로지스틱 회귀에 시그모이드 함수를 쓰는 경우

  • Sigmoid 함수는 0 또는 1에 가까워지면 그래프의 기울기가 완만해지고, 주황색 부분은 기울기가 0에 아주 가깝고 그러다 보니 역전파 과정을 거치면서 뒤에서부터 미분한 값을 앞에서 곱하는게 되는데 그런 과정을 거치다 보니 앞단에는 기울기가 잘 전달되지 않는 문제가 발생함!
    → 그 문제 : Gradient Vanishinng Problem

 

Gradient Vanishinng Problem ★

  • 시그모이드 같은 함수를 쓰게되면 기울기가 완전히 0에 수렴하게 되면서, 역전파하는 과정에서 앞으로 갈수록 기울기가 제대로 전달이 안되면서 0에 매우 가까운 값이 계속 곱해서 넘어가다보니 Weight 가 제대로 학습이 잘 안된다.
    → Gradient가 점점 사라지고 있는 문제임
  • Sigmoid 뿐만 아니라 tanh나 activation function(활성화 함수)도 시그모이드랑 비슷하게 생겨서 함수를 거치면서 출력이 점점 작아짐
  • 네트워크가 깊어질수록 더욱 심각해지는 현상이 있음
  • ReLU와 같은 activation function을 활용하면 많이 완화되는 효과가 있음

 

하이퍼볼릭탄젠트 함수 (Hyperbolic Tangent Function) - tanh

  • Sigmoid 함수랑 생긴건 똑같은데 기울기가 조금 다름 → 시그모이드는 0과1 이지만, 하이퍼볼릭찬젠트는 -1과 1 사이다
  • 시그모이드 함수보다는 적지만, 유사하게 gradient vanishing 문제 발생

 

렐루 함수(ReLU)

  • Sigmoid 함수와 tanh에서 해결못한 gradient vanishing 문제를 해결하기 위해 0보다 클때는 선형으로 0보다 작을 때는 0을 줌
  • 양수값에선 특정 값에 수렴하지 않아, 시그모이드 함수나 하이퍼볼릭탄젠트에 비해 더 잘 동작하며, gradient vanishing 문제도 많이 사라짐,, 연산도 간단하여 속도도 훨씬 빠름
  • 입력값이 음수이면 기울기가 0이 되어, 뉴런이 회생할 수 없다는 뜻의 죽은 렐루(dying ReLU)현상

 

리키 함수(Leaky ReLU)

  • ReLU를 보완하기 위한 ReLU 함수의 변형
  • 기울기가 다르되 입력값이 음수일땐 조금씩 변경하고 음력값이 양수 일 때는 크게 변경함 → 입력값이 작을때는 작게 새는 것 같은 느낌으로 값을 변형한다고 해서 Leaky 함수라고 함

 

 

Softmax 함수

  • 분류를 위해서 사용하는 함수
    → XOR-2 예제에서 앞의 Layer를 ReLu를 썼고 뒤의 Layer에서 softmax를 썼음
    → 마지막에 분류하는 Layer에서 활용되는 활성화 함수
  • 분류해야하는 정답의 개수를 k라고 할 때, k차원의 벡터를 입력받아 각 클래스에 대한 확률을 추정

→ z에 예측값들이 다양하게 나오는데 그것이 softmax Layer를 거치면 다합쳐서 1이 되도록 변경이 됨

→ 그래서 실제값은 0 1 0인데 z에서는 이상한 값이 나왔을꺼임,, 어쨋든 두번째가 0.7로 쓰기 때문에 z에서도 두번째가 제일 크긴 했을텐데 마이너스 값도 많이 나오고 하다보니 그것들을 다 합쳐서 분류에 대한 클래스에 대한 확률을 다 합쳐서 1로 만들어주도록 변경해주는 것

→ 분류에서는 softmax를 거친값이랑 실제값이랑 cross entropy 함수로 loss function을 구해준다.

반응형
반응형

퍼셉트론(Perceptron)

  • 퍼셉트론은 초기 형태의 인공 신경망으로, 다수 입력으로부터 하나의 결과를 내보내는 알고리즘
  • 뉴런을 흉내내어 만든 구조

→ 이런 수식을 보여주는데 , 여기서 i가 한개밖에 없으면 결국 선형회귀랑 똑같음 !!

  • 인공신경망은 퍼셉트론을 여러층 쌓고 이렇게 만듬
  • 결국 선형회귀랑 로지스틱회귀를 여러개 겹쳐서 사용하면 인공신경망에 쓰는 딥러닝이 되는 구조
그래서 선형회귀랑 로지스틱 회귀를 잘 이해하고 넘어가야 함
거의 선형회귀랑 로지스틱회귀가 딥러닝의 밑거름

 

XOR 문제

→ AND 나 OR 같은 경우 선을 하나만 그으면 분류가 가능함 (선형회귀, 로지스틱 회귀)

→ XOR 는 선 하나만 가지고 분류가 불가능함

 

왜 인공지능에 딥러닝이 나왔는가 ?? (XOR 문제)

  • 하나의 퍼셉트론은 선형으로만 분리할 수 있어, XOR은 풀 수 없음
  • 퍼셉트론을 여러 층으로 쌓으면 곡선으로도 분리할 수 있음,, 그래서 딥러닝이 등장함!
    다층 퍼셉트론 (MultiLayer Perceptron, MLP) - 딥러닝의 제일 시초
  • 다층 퍼셉트론처럼 은닉층이 2개 이상인 경우, 심층 신경망 (Deep Neural Network, DNN)이라고 부름

 

XOR 문제 실습 1

  • 단순 로지스틱 회귀 → XOR 문제를 해결할 수 없음
import numpy as np
import tensorflow as tf

 

  • Input 정의
    • 00 → 0 , 01 → 1 , 10 → 1 , 11 → 0
input = np.array([[0,0], [0,1], [1,0], [1,1]]).astype(np.float)
output = np.array([[0], [1], [1], [0]]).astype(np.float)

 

  • tensorflow 를 활용해서 모델 생성
    • Input 데이터가 두개가 들어오면 거기에 대해서 Dense 라는 Layer를 추가
    • → 퍼셉트론이라고 생각하면 됨
    • → sigmoid 함수를 썼는데 1층만 있으면 결국 Logistic regression이랑 똑같음
model = tf.keras.Sequential([
    tf.keras.layers.Input(shape=2, dtype='float32'), # Input 정의
    tf.keras.layers.Dense(1, activation='sigmoid') # 실질적인 층
])

model.summary() # param:3 -> W:2, b:1

→ parameter 수가 3개라고 나옴,, Input 에서 두개가 들어오기때문에 두개에 대한 각각의 W가 생성이 되고 W 두개에 b가 한개 !!

 

  • 로지스틱 회귀랑 선형회귀에서 계속 학습할 때 썼던 GD를 SGD이라고 생각하면 됨
    • SGD는 Gradient Descent 위에 momentum이라고 생각하면 됨
optimizer = tf.keras.optimizers.SGD(lr=0.01, decay=0, momentum=0.99, nesterov=True)
model.compile(optimizer=optimizer, loss='mse', metrics=['accuracy']) 

# 학습 fit() 함수 호출
model.fit(input, output, epochs=10)

→ 파라미터 3개에 대해서 10번 학습하는데 계속 정확도가 50밖에 안나옴

→ XOR 문제를 풀 수가 없어서 50밖에 안나옴

 

아무리 학습을 해도 50점밖에 안되는 구조가 있어서 그런 부분을 수학적으로 풀어주기 위해서 층을 더 쌓으면 풀 수 있다 !!
반응형

XOR 문제 실습 2

  • 다층 퍼셉트론 → XOR 문제 해결 가능
import numpy as np
import tensorflow as tf

input = np.array([[0,0], [0,1], [1, 0], [1,1]]).astype(np.float)
output = np.array([[1,0], [0, 1], [0, 1], [1, 0]]).astype(np.float)

 

  • 모델 생성
model = tf.keras.Sequential([
                             tf.keras.layers.Input(shape=2, dtype='float32'),
                             tf.keras.layers.Dense(4, activation='relu'),
                             tf.keras.layers.Dense(4, activation='relu'),
                             tf.keras.layers.Dense(2, activation='softmax')
                             ])
                             
model.summary()

 

  • binary_crossentropy
optimizer = tf.keras.optimizers.SGD(lr=0.01, decay=0, momentum=0.99, nesterov=True)
model.compile(optimizer=optimizer, loss='binary_crossentropy', metrics=['accuracy'])

 

  • 학습
model.fit(input, output, epochs=30)

→ 30번쯤 돌리니 정확도가 1점이 나옴 !! 드디어 !!!

 

XOR-1 에서는 모델에서 층을 하나만 줬음
XOR-2 에서는 모델에서 층을 3개를 쓰고, loss function도 binary_crossentropy 으로 바꿔줌
→ cross entropy가 분류에서 많이 씀
→ 멀티 Layer로 모델을 바꿔주고 학습을 하니깐 성능이 좋아짐
→ 이런식의 문제를 풀기 위해서 처음에는 단층을 썼었는데 XOR 문제도 당장 못풀기때문에 그부분을 해결하기 위해 다층 퍼셉트론으로 바꾸면서 DNN이 등장함 !!

 

반응형
반응형

SVM(Support Vector Machine)

  • 머신러닝에서는 딥러닝이 활발해지기 전까지 제일 많이 활용됨

→ 흰색원 , 검은색원을 분류를 할 수 있는 기준을 찾는 것

  • logistic regression은 함수의 fitting을 하면서 찾았고 SVM은 각 데이터들 사이에 선을 그을때 마진 (선이랑 가까운 데이터들의 거리) 을 최대한으로 그려주는 선을 찾는다.

 

SVM 실습

https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html?highlight=svc#sklearn.svm.SVC 
→ 파라미터 찾는 사이트
★ tensorflow가 딥러닝에 특화되어 있다면, scikit-learn은 기존의 머신러닝 알고리즘에 사용 가능하고 기초적인 딥러닝까지 가능한 라이브러리임 !
import numpy as np
import matplotlib.pyplot as plt

# scikit learn 알고리즘 - machine learning 
from sklearn.datasets.samples_generator import make_blobs
from sklearn.svm import SVC

 

  • 임의의 데이터 생성 → 두개의 센터로 만들어서 50개 데이터를 만들어줌
X, y = make_blobs(n_samples=50, centers=2, random_state=0, cluster_std=0.60)
plt.scatter(X[:,0], X[:, 1], c=y, s=50, cmap='autumn')

 

  • 임의의 데이터를 분류할 수 있는 선 생성
xfit = np.linspace(-1, 3.5)
plt.scatter(X[:,0], X[:,1], c=y, s=50, cmap='autumn')

for m,b in [(1,0.65), (0.5, 1.6), (-0.2, 2.9)]:
  plt.plot(xfit, m*xfit+b, '-k')

plt.xlim(-1, 3.5);

 

xfit = np.linspace(-1, 3.5)
plt.scatter(X[:,0], X[:,1], c=y, s=50, cmap='autumn')

for m,b in [(1,0.65), (0.5, 1.6), (-0.2, 2.9)]:
  plt.plot(xfit, m*xfit+b, '-k')

plt.xlim(-1, 3.5);

plt.plot([0.6], [2.1], 'x', color='blue', markeredgewidth=2, markersize=10)
plt.plot([3.0], [3.2], 'x', color='blue', markeredgewidth=2, markersize=10)

 

→ 선을 세개로 그을 수 있는데 임의의 데이터(X)가 들어왔을 때, 첫번째 선과 두번째 선이랑 분류결과가 다르게 나올 수 있기때문에 최적의 평균을 찾기 위해서 SVM을 돌린다.

 

  • 모델 선언
    • scikit-learn의 SVC 사용
    • kernel = 'linear' → 직선
    • model.fit( ) 함수를 호출하면 학습이 완료됨
model = SVC(kernel='linear', C=1E10) # Support Vector Classifier
model.fit(X, y)

 

  • 그림 그리기
def plot_svc_decision_function(model, ax=None, plot_support=True):
    """Plot the decision function for a 2D SVC"""
    if ax is None:
        ax = plt.gca()
    xlim = ax.get_xlim()
    ylim = ax.get_ylim()
    
    # create grid to evaluate model
    x = np.linspace(xlim[0], xlim[1], 30)
    y = np.linspace(ylim[0], ylim[1], 30)
    Y, X = np.meshgrid(y, x)
    xy = np.vstack([X.ravel(), Y.ravel()]).T
    P = model.decision_function(xy).reshape(X.shape)
    
    # plot decision boundary and margins
    ax.contour(X, Y, P, colors='k',
               levels=[-1, 0, 1], alpha=0.5,
               linestyles=['--', '-', '--'])
    
    # plot support vectors
    if plot_support:
        ax.scatter(model.support_vectors_[:, 0],
                   model.support_vectors_[:, 1],
                   s=300, linewidth=1, facecolors='none');
    ax.set_xlim(xlim)
    ax.set_ylim(ylim)
plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
plot_svc_decision_function(model);

→ SVM을 학습하는 도구가 가장 가까운 데이터들에서 마진을 최대로 잡을 수 있는 선을 찾는다.

 

plt.scatter(X[:, 0], X[:, 1], c=y, s=50, cmap='autumn')
plt.plot([0.6], [2.1], 'x', color='blue', markeredgewidth=2, markersize=10)
plot_svc_decision_function(model);

 

→ 아까 넣었던 임의의 데이터를 넣으면 선을 기준으로 노란색 원들과 더 가깝기 때문에 노란색으로 분류가 된다.

 

반응형

K-means clustering

  • 머신러닝에서 비지도 학습의 대표적인 방법
  • 위에서 배웠던 Linear, Logistic regression , SVM은 다 X에 따라서 y의 값이 있었고 어떤게 분류인지 이런 값이 있다던지, 선형회귀는 입력값에 대한 y값이 존재했는데 K-means clustering은 label이 없이 진행됨
  • Original data 가 아무색도 없어서 몇개로 묶을 것인지 지정이 가능함 (K값 = 2)
    1. K값을 정하면 점이 K값만큼 생성된다.
    2. 모든 데이터에서 이 점들이랑 거리를 어떤게 더 가까운지 판별을 하고 가까운거에 대해서 cluster를 묶어준다.
    3. cluster로 묶어주고 cluster 내에 있는 점들을 활용해서 Centroid - 중심점을 옮겨주고 중심점이 옮겨진 후 한번 더 전체 데이터에 대해서 중심점에 대해서 어떤게 더 가까운지 다시 분류한다 !!!!!!
    4. 다시 묶은 다음 cluster를 옮기고 다시 또 !! 전체 데이터에서 분류를 한다,,
    → 이런 과정을 반복

 

실사용 예시 )

쇼핑몰에서 티셔츠 사이즈를 사람들의 키와 몸무게에 대한 데이터를 가지고 클러스터를 만든다.

→ 사이즈 추천

 

SVM 같은 경우에는 실제로 분류를 해야되는 경우에서 활용이 되는데, K-means clustering 은 분류없이 오리지널 데이터에서 클러스터링을 하고 클러스터를 나눔

 

K-means clustering 구현

  1. 주어진 기본 코드를 이용하여 데이터 생성
  2. K 값은 2 (랜덤한 좌표를 갖는 두 점을 생성)
  3. 수식을 이용하여 모든 데이터와 Ki 값 사이의 거리를 계산
  4. 데이터가 K1에 가까우면 K1으로 분류, 데이터가 K2에 가까우면 K2로 분류
  5. 분류된 값들의 x, y 좌표 평균값을 구함
  6. centroid 업데이트
  7. 3~6번 (epochs)과정을 여러번 반봅
  8. 결과 출력

3번 수식

 

K-means clustering 실습

  • Import Libraries
import numpy as np
import matplotlib.pyplot as plt
import random
# Use matplotlib in notebook output
%matplotlib inline

 

  • 데이터 정의
    • 먼저 알고리즘을 테스트 할 데이터를 정의합니다. 이 노트북에서 사용하고있는 데이터는 가짜 데이터이지만 이해하기 위해 축구 경기의 선수 통계라고 생각해 봅시다.
# Data - [average passes, average goals (player goals - opponent goals)]
X = [[100,5], [90,5], [110,5], [97,4], [102,4], [112,4], [92,4], [95,3], [90,3], [100,3],
     [110,5], [100,5], [110,4], [93,3], [107,2], [117,3], [96,2], [105,3], [100,3], [110,3],
     [60,-1], [70,-1],[40,1], [70,-3], [50,-1], [80,0],[50,0],[60,-1],[60,1],[55,0],
     [40,-1], [45,-1],[40,0], [55,-3], [60,-1], [65,0],[70,0],[51,-2],[51,1],[48,0]]

 

  • 2D 그래프에 데이터 플로팅
plotx = []
ploty = []
for i in range(len(X)):
    plotx.append(X[i][0])
    ploty.append(X[i][1])
    # print(plotx, ploty)
plt.plot(plotx,ploty, 'bo')

def random_centers(dim,k):
    centers = []
    for i in range(k):
        center = []
        for d in range(dim):
            rand = random.randint(0,100)
            center.append(rand)
        centers.append(center)
    return centers

def point_clustering(data, centers, dims, first_cluster=False):
    for point in data:
        nearest_center = 0
        nearest_center_dist = None
        for i in range(0, len(centers)):
            euclidean_dist = 0
            for d in range(0, dims):
                dist = abs(point[d] - centers[i][d])
                euclidean_dist += dist
            euclidean_dist = np.sqrt(euclidean_dist)
            if nearest_center_dist == None:
                nearest_center_dist = euclidean_dist
                nearest_center = i
            elif nearest_center_dist > euclidean_dist:
                nearest_center_dist = euclidean_dist
                nearest_center = i
        if first_cluster:
            point.append(nearest_center)
        else:
            point[-1] = nearest_center
    return data

def mean_center(data, centers, dims):
    print('centers:', centers, 'dims:', dims)
    new_centers = []
    for i in range(len(centers)):
        new_center = []
        n_of_points = 0
        total_of_points = []
        for point in data:
            if point[-1] == i:
                n_of_points += 1
                for dim in range(0,dims):
                    if dim < len(total_of_points):
                        total_of_points[dim] += point[dim]
                    else:
                        total_of_points.append(point[dim])
        if len(total_of_points) != 0:
            for dim in range(0,dims):
                print(total_of_points, dim)
                new_center.append(total_of_points[dim]/n_of_points)
            new_centers.append(new_center)
        else: 
            new_centers.append(centers[i])
        
            
    return new_centers

 

  • K- 평균 클러스터링 알고리즘
# Gets data and k, returns a list of center points.
def train_k_means_clustering(data, k=2, epochs=5):
    dims = len(data[0])
    print('data[0]:',data[0])
    centers = random_centers(dims,k)
    
    clustered_data = point_clustering(data, centers, dims, first_cluster=True)

    for i in range(epochs):
        centers = mean_center(clustered_data, centers, dims)
        clustered_data = point_clustering(data, centers, dims, first_cluster=False)
    
    return centers

def predict_k_means_clustering(point, centers):
    dims = len(point)
    center_dims = len(centers[0])
    
    if dims != center_dims:
        raise ValueError('Point given for prediction have', dims, 'dimensions but centers have', center_dims, 'dimensions')

    nearest_center = None
    nearest_dist = None
    
    for i in range(len(centers)):
        euclidean_dist = 0
        for dim in range(1, dims):
            dist = point[dim] - centers[i][dim]
            euclidean_dist += dist**2
        euclidean_dist = np.sqrt(euclidean_dist)
        if nearest_dist == None:
            nearest_dist = euclidean_dist
            nearest_center = i
        elif nearest_dist > euclidean_dist:
            nearest_dist = euclidean_dist
            nearest_center = i
        print('center:',i, 'dist:',euclidean_dist)
            
    return nearest_center
centers = train_k_means_clustering(X, k=2, epochs=5)

print(centers)

 

point = [110,3]
print(predict_k_means_clustering(point, centers))

plt.plot(plotx,ploty, 'bo', centers[0][0], centers[0][1],'ro', centers[1][0], centers[1][1], 'go')

반응형

+ Recent posts