Deeplearning - chapter3

심준보·2023년 4월 10일
post-thumbnail

chapter 3

  • 케라스와 텐서플로 소개

텐서 종류

  • 1

import tensorflow as tf

x = tf.ones(shape=(2,1))
print(x)
  • 0
x = tf.zeros(shape =(2,1))
print(x)
  • random
x = tf.random.normal(shape=(3,1),mean=0. , stddev=1.)

print(x)

mean: 평균 , stddev =표준편차를 의미

normal은 평균 ,표준편차를 기반으로 무작위 생성 -> 정규분포에서 값을 생성


x = tf.random.uniform(shape=(3, 1), minval=0., maxval=1.)

minval :생성될 값의 최솟값 , maxval : 생성될 값의 최댓값

uniform 은 최솟값 최댓값 기반으로 -> 균등분포에서 값을 생성


  • numpy 배열에 값 할당

import numpy as np
x = np.ones(shape=(2, 2))
x[0, 0] = 0.

output :


array([[0., 1.],
       [1., 1.]])
  • 텐서플로우 변수 만들기
v = tf.Variable(initial_value=tf.random.normal(shape=(3, 1)))

tf.Variable() 함수는 TensorFlow에서 변수를 생성하는 함수

initial_value = 초기값 생성

  • 텐서플로 변수에 값 할당
v.assign(tf.ones((3, 1)))
  • assign_add 사용
v.assign_add(tf.ones((3, 1)))
  • 기본적 수학연산
b = tf.square(v)   


square 가 제곱이라는 의미

c = tf.sqrt(a)    

sqrt 는 제곱근의 의미

e = tf.matmul(a, b) 

matmul 은 두개의 행렬을 곱한다

GradientTape API

  • GradientTape 사용하기

input_var = tf.Variable(initial_value=3.)    

print(input_var)     
with tf.GradientTape() as tape:
   result = tf.square(input_var)
gradient = tape.gradient(result, input_var)

tape.gradient() 함수는 result 텐서와 input_var 변수를 입력으로 받아,
result 텐서의 각 원소에 대한 input_var 변수의 그래디언트 값을 계산

  • 상수 입력 텐서
input_const = tf.constant(3.)

constant 가 상수생성

2D 평면에 두 클래스의 랜덤한 포인트 생성하기

num_samples_per_class = 1000
negative_samples = np.random.multivariate_normal(
    mean=[0, 3],
    cov=[[1, 0.5],[0.5, 1]],
    size=num_samples_per_class)
positive_samples = np.random.multivariate_normal(
    mean=[3, 0],
    cov=[[1, 0.5],[0.5, 1]],
    size=num_samples_per_class)

num_samples_per_class : 클래스당 샘플수를 1000개로 지정

다중 정규 분포 -> multivariate normal

  • 두 클래스를 (2000,2) 크기의 한 배열로 쌓기

inputs = np.vstack((negative_samples, positive_samples)).astype(np.float32)

np.vstack(): NumPy 배열을 수직 방향으로 쌓아올리는 함수



두 클래스의 포인트를 그래프로 그리기

import matplotlib.pyplot as plt
plt.scatter(inputs[:, 0], inputs[:, 1], c=targets[:, 0])
plt.show()

자세히

plt.scatter(inputs[:, 0], inputs[:, 1], c=targets[:, 0])  
  • inputs[:, 0]: inputs 배열에서 첫 번째 열(column)의 값을 추출합니다. 이 값은 x축에 해당하는 값
  • inputs[:, 1]: inputs 배열에서 두 번째 열(column)의 값을 추출합니다. 이 값은 y축에 해당하는 값으로 사용
  • plt.scatter(): x축과 y축의 값을 사용하여 산점도(Scatter plot)를 그리는 함수


선형 분류기 변수 만들기

input_dim = 2
output_dim = 1
W = tf.Variable(initial_value=tf.random.uniform(shape=(input_dim, output_dim)))
b = tf.Variable(initial_value=tf.zeros(shape=(output_dim,)))
  • input_dim = 2
    입력데이터의 차원을 나타내는 변수 , 위에서 inputs의 배열의 열 수가 2 이므로 -> 2

  • output_dim = 1
    출력 데이터의 차원을 나타내는 변수 , 이진 분류 문제를 풀고 있으므로 , 1이 된다

  • W = tf.Variable(initial_value=tf.random.uniform(shape=(input_dim, output_dim)))
    가중치를 의미

  • b = tf.Variable(initial_value=tf.zeros(shape=(output_dim,)))

    편향을 의미 , 벡터 생성
    위 w,b 는 무작위로 초기화 된다.

    훈련 스텝 함수

  learning_rate = 0.1

def training_step(inputs, targets):
    with tf.GradientTape() as tape:
        predictions = model(inputs)              
        loss = square_loss(targets, predictions) 
    grad_loss_wrt_W, grad_loss_wrt_b = tape.gradient(loss, [W, b])
    W.assign_sub(grad_loss_wrt_W * learning_rate)   
    b.assign_sub(grad_loss_wrt_b * learning_rate)
    return loss
  • predictions = model(inputs)
    가중치와 편향을 사용하여 예측값을 계산한다.
  • loss = square_loss(targets, predictions)
    MSE 오차를 계산

  • grad_loss_wrt_W, grad_loss_wrt_b = tape.gradient(loss, [W, b])

계산된 그래디언트를 사용하여 , w 와 b 변수에 대한 그래디언트를 계산한다.

  • W.assign_sub(grad_loss_wrt_W * learning_rate)

W변수의 값을 업데이트한다. , assign_sub 는 현재값에서 뺴는 것이다.
gradient 반대 방향으로 일정한 속도로 이동한다

  • 산점도(
plt.scatter(inputs[:, 0], inputs[:, 1], c=predictions[:, 0] > 0.5)

예측값이 0.5보다 큰 경우를 true , 그렇지 않은 경우를 false로 나타내는 벡터를 만든다.

  • numpy
x = np.linspace(-1, 4, 100)

NumPy 라이브러리를 사용하여 -1부터 4까지의 범위를 100개의 동일한 간격으로 분할한 배열을 생성하는 코드

y = - W[0] /  W[1] * x + (0.5 - b) / W[1]

우선, x와 y의 관계식인 y = - W[0] / W[1] * x + (0.5 - b) / W[1]을 계산합니다. 이 식은 2차원 평면 상에서의 직선을 나타내며, 결정 경계를 나타냅니다.

신경망의 구조: 핵심 Keras API이해하기

  • Layer의 서브클래스로 구현한 Dense 층
from tensorflow import keras

class SimpleDense(keras.layers.Layer):

    def __init__(self, units, activation=None):
        super().__init__()
        self.units = units
        self.activation = activation

    def build(self, input_shape):  
        input_dim = input_shape[-1]
        self.W = self.add_weight(shape=(input_dim, self.units),
                                 initializer="random_normal")  
        self.b = self.add_weight(shape=(self.units,), 
                                 initializer="zeros")

    def call(self, inputs):           
        y = tf.matmul(inputs, self.W) + self.b
        if self.activation is not None:
            y = self.activation(y)
        return y

SimpleDense 클래스는 밀집 레이어(dense layer)를 구성하는 데 사용됩니다. 이 레이어는 입력값과 가중치를 곱하고 편향(bias)을 더한 후에 활성화 함수를 적용하여 출력값을 생성

init :계층의 단위(뉴런) 수 및 사용할 활성화 함수를 포함하여 계층의 속성을 초기화합니다.

build :메소드는 레이어가 모델에서 처음 사용될 때 호출되며 레이어의 가중치를 정의

call :방법은 레이어가 입력을 처리하는 방법을 정의

  • 이어서,

my_dense = SimpleDense(units=32, activation=tf.nn.relu) 
input_tensor = tf.ones(shape=(2, 784))                     
output_tensor = my_dense(input_tensor)                   
print(output_tensor.shape)

[1] 출력 크기 32 , 활성화 함수 RELU
[2] 크기가 (2,784) 인 입력 텐서를 생성한다.
[3] my_dense 객체를 사용하여 입력 텐서를 처리하여 출력 텐서(output tensor)를 생성 , 출력텐서의 크기는 (2,32)

자동 크기 추론: 동적으로 층 만들기


from tensorflow.keras import layers
layer = layers.Dense(32, activation="relu")

[1] from tensorflow.keras import layers 구문을 사용하여 Keras 라이브러리에서 layers 모듈을 임포트

[2] Dense 클래스를 사용하여 밀집 레이어(dense layer)를 구성합니다. 이 레이어는 입력값과 가중치를 곱하고 편향(bias)을 더한 후에 활성화 함수를 적용하여 출력값을 생성


from tensorflow.keras import models    #models 모델 임포트 
from tensorflow.keras import layers
model = models.Sequential([
    layers.Dense(32, activation="relu"),
    layers.Dense(32)                
])

Sequential : 레이러를 순차적으로 연결하여 모델을 생성한다.
layers.Dense(32) : 활성화 함수를 지정하지 않았으므로, 기본값으로 선형함수가 사용


model = keras.Sequential([
    SimpleDense(32, activation="relu"),
    SimpleDense(64, activation="relu"),
    SimpleDense(32, activation="relu"),
    SimpleDense(10, activation="softmax")
])

SimpleDense(32, activation="relu") :노드가 32개이고 , 활성화 함수:RELU사용


model = keras.Sequential([keras.layers.Dense(1)])
model.compile(optimizer="rmsprop",
              loss="mean_squared_error",
              metrics=["accuracy"])

keras.Sequential([keras.layers.Dense(1)]) : 이진분류 Dense 생성

  • 이어서 (optimizer , loss , metrics)

model.compile(optimizer="rmsprop",
loss="mean_squared_error",
metrics=["accuracy"])

compile : 메소드는 모델의 최적화 방법(optimizer), 손실 함수(loss), 평가 지표(metrics)를 지정

optimizer : 인자로는 rmsprop을 전달 rmsprop은 학습률(learning rate)을 조절하는 최적화 방법 중 하나

loss : 인자로는 mean_squared_error를 전달 , mean_squared_error는 평균 제곱 오차(MSE)를 계산하는 손실 함수
,MSE는 예측값과 실제값의 차이를 제곱하여 평균한 값으로, 값이 작을수록 모델의 예측이 정확

metrics : 인자로는 accuracy를 전달합니다. accuracy는 분류 문제에서 모델의 예측이 정확한 비율을 계산하는 평가 지표


metrics=[keras.metrics.BinaryAccuracy()])

BinaryAccuracy() : 클래스는 이진 분류 문제에서 모델의 예측이 정확한 비율을 계산하는 평가 지표

fit() 메서드 이해하기


history = model.fit(
    inputs,
    targets,
    epochs=5,
    batch_size=128
)

fit : 메소드는 입력 데이터(inputs), 목표 데이터(targets), 에포크 수(epochs), 배치 크기(batch_size) 등을 지정

history.history 

history.history : 학습 과정에서 발생한 손실(loss), 평가 지표(metrics) 등의 정보를 담은 딕셔너리를 반환

검증 데이터에서 손실과 측정 지표 모니터링 하기

  • Validation_data 매개변수 사용하기
indices_permutation = np.random.permutation(len(inputs))   
shuffled_inputs = inputs[indices_permutation]    
shuffled_targets = targets[indices_permutation]

len(inputs) : 함수를 사용하여 inputs 배열의 길이(데이터의 수)를 구합니다.

np.random.permutation : 함수를 사용하여 해당 길이를 인자로 넣어주면 0부터 해당 길이까지의 숫자가 랜덤한 순서로 섞인 배열을 반환합니다.

inputs와 targets : 배열에서 섞인 인덱스를 사용하여 각각 shuffled_inputs와 shuffled_targets 배열을 만듭니다.

추론: 훈련한 모델 사용하기

predictions = model.predict(val_inputs, batch_size=128) 

model.predict() : 함수는 모델을 사용하여 입력 데이터에 대한 예측값을 반환

val_inputs :모델의 입력으로 사용되는 데이터를 의미

batch_size=128 : 인자는 예측 작업을 수행할 때 데이터를 한 번에 처리하는 것이 아니라, 128개씩 묶어서 처리하도록 지정

profile
밑거름이라고생각합니다

0개의 댓글