### 2021.12.17

 

MNIST 손글씨 이미지 데이터셋

MNIST 데이터셋은 위 그림과 같이 0에서 9까지 10가지로 분류될 수 있는 손글씨 숫자 이미지 70,000개로 이루어져 있습니다.

각 이미지는 28×28 픽셀로 구성되고 각 픽셀은 아래와 같이 0~255 사이의 숫자 행렬로 표현됩니다.

 

이러한 60,000개의 이미지는 인공 신경망의 훈련 (Training)에 사용되고, 10,000개의 이미지는 테스트 (Test)에 사용됩니다.

 

이번 페이지에서는 Dense 층들로 구성되는 완전 연결된 인공신경망 (Fully-Connected Neural Network)을 이용해서 MNIST 데이터셋을 분류해 보겠습니다.

 

예제

import tensorflow as tf

# 1. MNIST 데이터셋 임포트
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# 2. 데이터 전처리
x_train, x_test = x_train/255.0, x_test/255.0

# 3. 모델 구성
model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(512, activation=tf.nn.relu),
    tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])

# 4. 모델 컴파일
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# 5. 모델 훈련
model.fit(x_train, y_train, epochs=5)

# 6. 정확도 평가
test_loss, test_acc = model.evaluate(x_test, y_test)
print('테스트 정확도:', test_acc)

model.save('my_model1.h5')
#Out[]
Epoch 1/5
1875/1875 [==============================] - 7s 4ms/step - loss: 0.2026 - accuracy: 0.9408
Epoch 2/5
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0808 - accuracy: 0.9753
Epoch 3/5
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0514 - accuracy: 0.9837
Epoch 4/5
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0376 - accuracy: 0.9880
Epoch 5/5
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0266 - accuracy: 0.9916
313/313 [==============================] - 1s 2ms/step - loss: 0.0643 - accuracy: 0.9811
테스트 정확도: 0.9811000227928162

 

설명

0. tensorflow 불러오기

#tensorflow 라이브러리를 불러옵니다.
import tensorflow as tf

 

1. MNIST 데이터셋 임포트

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

tensorflow에서 직접 MNIST 손글씨 이미지 데이터셋을 불러와서 사용합니다.

load_data() 함수는 x_train, y_train, x_test, y_test 네 개의 NumPy 어레이를 반환합니다.

x_train, x_test는 28×28 픽셀의 각 손글씨 이미지 데이터이고, y_train, y_test는 분류에 사용되는 0~9 사이의 레이블 값을 갖습니다.

#In[1]
print("x_train 데이터 형태 :", x_train.shape)
print("x_train[0] 데이터 형태 :", x_train[0].shape)
print("y_train 데이터 형태 :", y_train.shape)

#Out[1]
x_train 데이터 형태 : (60000, 28, 28)
x_train[0] 데이터 형태 : (28, 28)
y_train 데이터 형태 : (60000,)
#In[2]
num = x_train[0]
for i in range(28):
    for j in range(28):
         print("{:4d}".format(num[i][j]), end="")
    print()

#Out[2]

 

각 이미지는 28×28 픽셀로 구성되고 각 픽셀은 아래와 같이 0~255 사이의 숫자 행렬로 표현됩니다.

 

이러한 60,000개의 이미지는 인공 신경망의 훈련 (Training)에 사용되고, 10,000개의 이미지는 테스트 (Test)에 사용됩니다.

이번 페이지에서는 Dense 층들로 구성되는 완전 연결된 인공신경망 (Fully-Connected Neural Network)을 이용해서 MNIST 데이터셋을 분류해 보겠습니다.

 

2.  데이터 전처리

# 0 ~ 255.0 사이의 값을 갖는 픽셀값들을 0~1.0 사이의 값을 갖도록 변환합니다.

x_train, x_test = x_train/255.0, x_test/255.0

 

3.  모델 구성

model = tf.keras.models.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)),
    tf.keras.layers.Dense(512, activation=tf.nn.relu),
    tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])

tf.keras.models.Sequential()을 이용해서 인공신경망 모델을 구성합니다.

입력층 (Input layer)에서 Flatten()을 이용해서 28×28 픽셀의 값을 784개의 1차원 배열로 변환합니다.

다음 두 개의 뉴런 층 (Neuron layer)은 Dense()를 이용해서 완전 연결된 층 (Fully-connected layer)를 구성합니다.

각 층은 512개와 10개의 인공 뉴런 노드를 갖고 활성화 함수 (activation function)로는 각각 ReLU (tf.nn.relu)와 소프트맥스 (tf.nn.softmax)를 사용합니다.

 

4.  모델 컴파일

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

다음은 모델 컴파일 단계입니다. 학습 과정에서 손실 함수 (Loss function)를 줄이기 위해 사용되는 optimizer로는 Adam (Adaptive Momentum estimation)을 사용합니다.

손실 함수는 ‘sparse_categorical_crossentropy’를 지정하고, 평가 지표로는 정확도 (accuracy)를 사용합니다.

정확도는 테스트 이미지 중 올바르게 분류한 비율을 의미합니다.

 

5. 모델 훈련

#In[]
model.fit(x_train, y_train, epochs=5)

#Out[]
Epoch 1/5
1875/1875 [==============================] - 10s 5ms/step - loss: 0.1985 - accuracy: 0.9413
Epoch 2/5
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0806 - accuracy: 0.9743
Epoch 3/5
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0526 - accuracy: 0.9835
Epoch 4/5
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0373 - accuracy: 0.9881
Epoch 5/5
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0275 - accuracy: 0.9911
<tensorflow.python.keras.callbacks.History at 0x7fcb10ae1d90>

학습 과정은 위와 같이 이루어지며, 학습 데이터에 대한 정확도가 출력됩니다.

model.fit() 메서드에 학습 데이터와, 레이블, 에포크를 순서대로 입력하면, 학습이 이루어집니다.

에포크(epoch)는 60,000개의 전체 학습 데이터를 몇 번 반복해서 학습할지를 의미합니다.

model.save('my_model2.h5')

 

6. 정확도 평가

#In[]
test_loss, test_acc = model.evaluate(x_test, y_test)
print('테스트 정확도:', test_acc)

#Out[]
313/313 [==============================] - 1s 3ms/step - loss: 0.0707 - accuracy: 0.9785
테스트 정확도: 0.9785000085830688

결과는 위와 같습니다. 

model.evaluate()를 이용해서 10,000개의 테스트 샘플에 대해 손실 (loss)과 정확도 (accuracy)를 평가합니다.

 

간단한 인공신경망과 다섯 번 에포크의 학습만으로 98.02%의 정확도로 MNIST 이미지를 분류할 수 있음을 알 수 있습니다.

 

 

Matplotlib을 이용해서 에포크에 따른 정확도 (accuracy)와 손실 (loss) 값을 확인할 수 있습니다.

#In[]
loss, accuracy = [], []
for i in range(10):
    model.fit(x_train, y_train, epochs=1)
    loss.append(model.evaluate(x_test, y_test)[0])
    accuracy.append(model.evaluate(x_test, y_test)[1])

print(accuracy)
#Out[]
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0202 - accuracy: 0.9933
313/313 [==============================] - 1s 2ms/step - loss: 0.0603 - accuracy: 0.9814
313/313 [==============================] - 1s 2ms/step - loss: 0.0603 - accuracy: 0.9814
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0168 - accuracy: 0.9942
313/313 [==============================] - 1s 2ms/step - loss: 0.0819 - accuracy: 0.9775
313/313 [==============================] - 1s 2ms/step - loss: 0.0819 - accuracy: 0.9775
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0148 - accuracy: 0.9950
313/313 [==============================] - 1s 3ms/step - loss: 0.0738 - accuracy: 0.9806
313/313 [==============================] - 1s 3ms/step - loss: 0.0738 - accuracy: 0.9806
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0134 - accuracy: 0.9955
313/313 [==============================] - 1s 3ms/step - loss: 0.0662 - accuracy: 0.9833
313/313 [==============================] - 1s 2ms/step - loss: 0.0662 - accuracy: 0.9833
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0101 - accuracy: 0.9965
313/313 [==============================] - 1s 2ms/step - loss: 0.0771 - accuracy: 0.9820
313/313 [==============================] - 1s 2ms/step - loss: 0.0771 - accuracy: 0.9820
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0112 - accuracy: 0.9964
313/313 [==============================] - 1s 2ms/step - loss: 0.0744 - accuracy: 0.9821
313/313 [==============================] - 1s 2ms/step - loss: 0.0744 - accuracy: 0.9821
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0075 - accuracy: 0.9974
313/313 [==============================] - 1s 2ms/step - loss: 0.0820 - accuracy: 0.9828
313/313 [==============================] - 1s 2ms/step - loss: 0.0820 - accuracy: 0.9828
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0104 - accuracy: 0.9968
313/313 [==============================] - 1s 3ms/step - loss: 0.1053 - accuracy: 0.9808
313/313 [==============================] - 1s 2ms/step - loss: 0.1053 - accuracy: 0.9808
1875/1875 [==============================] - 10s 5ms/step - loss: 0.0066 - accuracy: 0.9979
313/313 [==============================] - 1s 2ms/step - loss: 0.0901 - accuracy: 0.9814
313/313 [==============================] - 1s 2ms/step - loss: 0.0901 - accuracy: 0.9814
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0084 - accuracy: 0.9975
313/313 [==============================] - 1s 3ms/step - loss: 0.0798 - accuracy: 0.9840
313/313 [==============================] - 1s 2ms/step - loss: 0.0798 - accuracy: 0.9840
[0.9814000129699707, 0.9775000214576721, 0.9805999994277954, 0.983299970626831, 0.9819999933242798, 0.9821000099182129, 0.9828000068664551, 0.9807999730110168, 0.9814000129699707, 0.984000027179718]

1회의 에포크마다 model.evaluate()의 loss, accuracy 값을 저장합니다.

결과는 아래와 같습니다.

model.save('my_model3.h5')
## Ex 10-6. MNIST 손글씨 인식 프로그램.

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import numpy as np
import tensorflow as tf


class MyApp(QMainWindow):

    def __init__(self):
        super().__init__()
        self.image = QImage(QSize(400, 400), QImage.Format_RGB32)
        self.image.fill(Qt.white)
        self.drawing = False
        self.brush_size = 30
        self.brush_color = Qt.black
        self.last_point = QPoint()
        self.loaded_model = None
        self.initUI()

    def initUI(self):
        menubar = self.menuBar()
        menubar.setNativeMenuBar(False)
        filemenu = menubar.addMenu('File')

        load_model_action = QAction('Load model', self)
        load_model_action.setShortcut('Ctrl+L')
        load_model_action.triggered.connect(self.load_model)

        save_action = QAction('Save', self)
        save_action.setShortcut('Ctrl+S')
        save_action.triggered.connect(self.save)

        clear_action = QAction('Clear', self)
        clear_action.setShortcut('Ctrl+C')
        clear_action.triggered.connect(self.clear)

        filemenu.addAction(load_model_action)
        filemenu.addAction(save_action)
        filemenu.addAction(clear_action)

        self.statusbar = self.statusBar()

        self.setWindowTitle('MNIST Classifier')
        self.setGeometry(300, 300, 400, 400)
        self.show()

    def paintEvent(self, e):
        canvas = QPainter(self)
        canvas.drawImage(self.rect(), self.image, self.image.rect())

    def mousePressEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.drawing = True
            self.last_point = e.pos()

    def mouseMoveEvent(self, e):
        if (e.buttons() & Qt.LeftButton) & self.drawing:
            painter = QPainter(self.image)
            painter.setPen(QPen(self.brush_color, self.brush_size, Qt.SolidLine, Qt.RoundCap))
            painter.drawLine(self.last_point, e.pos())
            self.last_point = e.pos()
            self.update()

    def mouseReleaseEvent(self, e):
        if e.button() == Qt.LeftButton:
            self.drawing = False

            arr = np.zeros((28, 28))
            for i in range(28):
                for j in range(28):
                    arr[j, i] = 1 - self.image.scaled(28, 28).pixelColor(i, j).getRgb()[0] / 255.0
            arr = arr.reshape(-1, 28, 28)

            if self.loaded_model:
                pred = self.loaded_model.predict(arr)[0]
                pred_num = str(np.argmax(pred))
                self.statusbar.showMessage('숫자 ' + pred_num + '입니다.')

    def load_model(self):
        fname, _ = QFileDialog.getOpenFileName(self, 'Load Model', '')

        if fname:
            self.loaded_model = tf.keras.models.load_model(fname)
            self.statusbar.showMessage('Model loaded.')

    def save(self):
        fpath, _ = QFileDialog.getSaveFileName(self, 'Save Image', '', "PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*) ")

        if fpath:
            self.image.scaled(28, 28).save(fpath)

    def clear(self):
        self.image.fill(Qt.white)
        self.update()
        self.statusbar.clearMessage()
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = MyApp()
    sys.exit(app.exec_())

 

 

 

 

 

### 2021.12.17

이전 페이지에서 각 뉴런층의 이름, 자료형, 활성화함수와 같은 다양한 정보를 확인하는 방법에 대해 알아보았습니다.

이 페이지에서는 특정 입력 데이터에 대해 각 뉴런층이 출력하는 값을 확인하는 방법에 대해 소개합니다.

 

훈련 데이터 준비하기

import tensorflow as tf
import numpy as np

tf.random.set_seed(0)


# 1. 훈련 데이터 준비하기
x_train = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
y_train = np.array([[0], [1], [1]])

우선 tf.random 모듈의 set_seed() 함수를 사용해서 랜덤 시드를 설정했습니다.

예제에서 x_train, y_train은 각각 훈련에 사용할 입력값, 출력값입니다.

이 페이지에서는 훈련은 진행하지 않고 입력 데이터 (x_train)에 대해 각 뉴런층이 출력하는 값을 확인합니다.

 

뉴런층 만들기

# 2. 뉴런층 만들기
input_layer = tf.keras.layers.InputLayer(input_shape=(3,))
hidden_layer = tf.keras.layers.Dense(units=4, activation='relu')
output_layer = tf.keras.layers.Dense(units=2, activation='softmax')

아래와 같은 간단한 신경망 모델을 구성하기 위한 뉴런층을 각각 만들었습니다.

길이 3을 갖는 벡터 입력을 받고, 은닉층은 네 개의 뉴런 노드를 가지며, 출력층은 두 개의 뉴런 노드를 가집니다.

은닉층의 활성화함수는 ‘relu’, 출력층의 활성화함수는 ‘softmax’로 지정했습니다.

Neural Network 구성하기

# 3. 모델 구성하기
model = tf.keras.Sequential([
  input_layer,
  hidden_layer,
  output_layer
  ])

tf.keras 모듈의 Sequantial 클래스는 Neural Network의 각 층을 순서대로 쌓을 수 있도록 합니다.

앞에서 만든 뉴런층을 순서대로 입력해서 신경망 모델을 구성합니다.

 

Neural Network 컴파일하기

# 4. 모델 컴파일하기
model.compile(loss='mse', optimizer='Adam')

손실 함수로 ‘mse’를, 옵티마이저로 ‘Adam’을 지정했습니다.

이 페이지의 예제에서는 훈련을 진행하지 않기 때문에 컴파일 과정은 생략할 수 있습니다.

 

은닉층의 출력값 확인하기

# 5. 은닉층의 출력 확인하기
intermediate_layer_model = tf.keras.Model(inputs=model.input, outputs=model.layers[0].output)
intermediate_output = intermediate_layer_model(x_train)

print('======== Inputs ========')
print(x_train)

print('\n======== Weights of Hidden Layer ========')
print(hidden_layer.get_weights()[0])

print('\n======== Outputs of Hidden Layer ========')
print(intermediate_output)
#Out[]
======== Inputs ========
[[1 0 0]
 [0 1 0]
 [0 0 1]]

======== Weights of Hidden Layer ========
[[-0.3851872  -0.54333335  0.0655309   0.1134268 ]
 [-0.15428883  0.5699866  -0.01254469  0.9223561 ]
 [ 0.36428273 -0.6936733   0.38850498  0.30073535]]

======== Outputs of Hidden Layer ========
tf.Tensor(
[[0.         0.         0.0655309  0.1134268 ]
 [0.         0.5699866  0.         0.9223561 ]
 [0.36428273 0.         0.38850498 0.30073535]], shape=(3, 4), dtype=float32)

tf.keras 모듈의 Model 클래스를 사용해서 새로운 모델 (intermediate_layer_model)을 하나 만들었습니다.

이 모델은 앞에서 구성한 전체 모델의 입력을 입력으로 하고,

첫번째 뉴런층 (hidden_layer)의 출력을 출력으로 하는 신경망 모델입니다.

이 모델에 훈련 데이터 (x_train)을 입력하면 첫번째 뉴런층의 출력을 반환합니다.

 

첫번째 뉴런층, 즉 은닉층의 출력은 아래와 같이 계산됩니다.

우선 입력 데이터 [1, 0, 0]에 대해 은닉층의 시냅스 가중치가 곱해집니다.

즉, 입력층 첫번째 노드의 입력 1에 시냅스 가중치 [-0.3851872 -0.54333335 0.0655309 0.1134268 ]가 곱해집니다.

다음으로 은닉층의 활성화함수인 ReLU (Rectified Linear Unit)가 적용되어서

0보다 작은 값은 0이되고, 0보다 큰 값은 그대로 출력값이 됩니다.

 

출력층의 출력값 확인하기

# 6. 출력층의 출력 확인하기
pred = model.predict(x_train)

print('\n======== Outputs of Output Layer ========')
print(pred)
#Out[]
======== Outputs of Output Layer ========
[[0.45516008 0.5448399 ]
 [0.18469977 0.8153002 ]
 [0.4541021  0.5458979 ]]

전체 신경망의 출력값은 Model 클래스의 predict() 메서드를 사용해서 간단하게 얻을 수 있습니다.

세 개의 값을 갖는 세 개의 입력 데이터 벡터에 대해 두 개의 값을 갖는 벡터 세 개를 출력합니다.

 

전체 예제 코드

import tensorflow as tf
import numpy as np

tf.random.set_seed(0)


# 1. 훈련 데이터 준비하기
x_train = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
y_train = np.array([[0], [1], [1]])


# 2. 뉴런층 만들기
input_layer = tf.keras.layers.InputLayer(input_shape=(3,))
hidden_layer = tf.keras.layers.Dense(units=4, activation='relu')
output_layer = tf.keras.layers.Dense(units=2, activation='softmax')


# 3. 모델 구성하기
model = tf.keras.Sequential([
  input_layer,
  hidden_layer,
  output_layer
  ])

# 4. 모델 컴파일하기
model.compile(loss='mse', optimizer='Adam')


# 5. 은닉층의 출력 확인하기
intermediate_layer_model = tf.keras.Model(inputs=model.input, outputs=model.layers[0].output)
intermediate_output = intermediate_layer_model(x_train)

print('======== Inputs ========')
print(x_train)

print('\n======== Weights of Hidden Layer ========')
print(hidden_layer.get_weights()[0])

print('\n======== Outputs of Hidden Layer ========')
print(intermediate_output)

# 6. 출력층의 출력 확인하기
pred = model.predict(x_train)

print('\n======== Outputs of Output Layer ========')
print(pred)
#Out[]
======== Inputs ========
[[1 0 0]
 [0 1 0]
 [0 0 1]]

======== Weights of Hidden Layer ========
[[-0.3851872  -0.54333335  0.0655309   0.1134268 ]
 [-0.15428883  0.5699866  -0.01254469  0.9223561 ]
 [ 0.36428273 -0.6936733   0.38850498  0.30073535]]

======== Outputs of Hidden Layer ========
tf.Tensor(
[[0.         0.         0.0655309  0.1134268 ]
 [0.         0.5699866  0.         0.9223561 ]
 [0.36428273 0.         0.38850498 0.30073535]], shape=(3, 4), dtype=float32)

======== Outputs of Output Layer ========
[[0.45516008 0.5448399 ]
 [0.18469977 0.8153002 ]
 [0.4541021  0.5458979 ]]

### 2021.12.17

tf.keras.layers.Layer는 Neural Network의 모든 레이어 객체가 상속하는 클래스입니다.

tf.keras.layers.Layer의 다양한 속성 (Attribute)을 이용해서 각 레이어에 대한 정보를 확인할 수 있습니다.

 

뉴런층의 이름(name)과 자료형 (dtype)

import tensorflow as tf

tf.random.set_seed(0)


# 1. 뉴런층 만들기
input_layer = tf.keras.layers.InputLayer(input_shape=(3,))
hidden_layer = tf.keras.layers.Dense(units=4, activation='relu')
output_layer = tf.keras.layers.Dense(units=2, activation='softmax')


# 2. 모델 구성하기
model = tf.keras.Sequential([
    input_layer,
    hidden_layer,
    output_layer
    ])


# 3. 모델 컴파일하기
model.compile(loss='mse', optimizer='Adam')


# 4. 뉴런층의 이름과 자료형
print(input_layer.name, input_layer.dtype)
print(hidden_layer.name, hidden_layer.dtype)
print(output_layer.name, output_layer.dtype)
#Out[]
input_1 float32
dense float32
dense_1 float32

name은 뉴런층의 이름입니다.

dtype은 뉴런층의 연산과 웨이트 값에 사용되는 자료형입니다.

아래와 같은 방법으로도 뉴런층의 속성을 확인할 수 있습니다.

print(model.layers[0].name)
print(model.layers[1].name)
print(model.layers[2].name)
#Out[]
dense
dense_1
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
/var/folders/xx/_99p48vj7pg7bs_kpl7838_00000gn/T/ipykernel_92980/147579868.py in <module>
      1 print(model.layers[0].name)
      2 print(model.layers[1].name)
----> 3 print(model.layers[2].name)

IndexError: list index out of range

model.layers는 구성한 Neural Network 모델의 (입력층을 제외한) 뉴런층 레이어 객체를 리스트의 형태로 반환합니다.

model.layers[0]은 모델의 첫번째 뉴런층, 즉 은닉층 (hidden layer)입니다.

model.layers[1]은 모델의 두번째 뉴런층, 즉 출력층 (output_layer)입니다.

모델이 (입력층을 제외한) 두 개의 뉴런층을 포함하기 때문에

model.layers[2].name을 출력하면 에러를 발생합니다.

 

뉴런층의 입력(input)과 출력(output)

print(input_layer.input)
print(input_layer.output)
print()

print(hidden_layer.input)
print(hidden_layer.output)
print()

print(hidden_layer.input.shape)
print(hidden_layer.output.shape)
print()

print(output_layer.input)
print(output_layer.output)
#Out[]
Tensor("input_1:0", shape=(None, 3), dtype=float32)
Tensor("input_1:0", shape=(None, 3), dtype=float32)

Tensor("input_1:0", shape=(None, 3), dtype=float32)
Tensor("dense/Relu:0", shape=(None, 4), dtype=float32)

(None, 3)
(None, 4)

Tensor("dense/Relu:0", shape=(None, 4), dtype=float32)
Tensor("dense_1/Softmax:0", shape=(None, 2), dtype=float32)

input은 뉴런층의 입력 텐서 (input tensor)입니다.

output은 뉴런층의 출력 텐서 (output tensor)입니다.

은닉층 (hidden_layer)의 입력과 출력의 형태 (shape)를 출력해보면

입력 텐서는 길이 3의 형태, 출력 텐서는 길이 4의 형태를 가짐을 알 수 있습니다.

예를 들어, (None, 3)은 길이 3의 벡터의 시퀀스형태가 될 수 있음을 의미합니다.

 

뉴런층의 활성화함수 (activation)

#In[]
print(hidden_layer.activation)
print(hidden_layer.activation.__name__)
print(output_layer.activation)
print(output_layer.activation.__name__)

#Out[]
<function relu at 0x7fceb66d0430>
relu
<function softmax at 0x7fceb66bdd30>
softmax

activation은 뉴런 노드의 활성화함수 (Activation function)를 나타냅니다.
"__Name"__"*을 사용해서 활성화함수의 이름을 출력했습니다.

뉴런층의 가중치 (weights)

#In[]
print(hidden_layer.weights)
print()
print(output_layer.weights)

#Out[]
[<tf.Variable 'dense/kernel:0' shape=(3, 4) dtype=float32, numpy=
array([[-0.3851872 , -0.54333335,  0.0655309 ,  0.1134268 ],
       [-0.15428883,  0.5699866 , -0.01254469,  0.9223561 ],
       [ 0.36428273, -0.6936733 ,  0.38850498,  0.30073535]],
      dtype=float32)>, <tf.Variable 'dense/bias:0' shape=(4,) dtype=float32, numpy=array([0., 0., 0., 0.], dtype=float32)>]

[<tf.Variable 'dense_1/kernel:0' shape=(4, 2) dtype=float32, numpy=
array([[ 0.11082816, -0.55741405],
       [ 0.7298498 ,  0.5545671 ],
       [ 0.29023337,  0.0607245 ],
       [-0.971118  ,  0.74701834]], dtype=float32)>, <tf.Variable 'dense_1/bias:0' shape=(2,) dtype=float32, numpy=array([0., 0.], dtype=float32)>]

weights를 사용해서 각 뉴런층의 시냅스 가중치에 대한 정보를 얻을 수 있습니다.

get_weights() 메세드

#In[]
print(hidden_layer.get_weights())
print()
print(output_layer.get_weights())

#Out[]
[array([[-0.3851872 , -0.54333335,  0.0655309 ,  0.1134268 ],
       [-0.15428883,  0.5699866 , -0.01254469,  0.9223561 ],
       [ 0.36428273, -0.6936733 ,  0.38850498,  0.30073535]],
      dtype=float32), array([0., 0., 0., 0.], dtype=float32)]

[array([[ 0.11082816, -0.55741405],
       [ 0.7298498 ,  0.5545671 ],
       [ 0.29023337,  0.0607245 ],
       [-0.971118  ,  0.74701834]], dtype=float32), array([0., 0.], dtype=float32)]

get_weights() 메서드를 사용하면 시냅스 가중치를 NumPy 어레이 형태로 얻을 수 있습니다.

### 2021.12.16

AND 연산은 논리 연산 (Logic operation)의 한 종류로 위의 그림과 같이 두 상태가 모두 참 (True, 1)일 때 참이고,

둘 중 하나라도 거짓 (False, 0)이라면 거짓이 되는 연산입니다.

전기 신호가 0과 1로 구성되어 있는 디지털 회로에서는 트랜지스터 게이트의 조합으로 구현할 수 있습니다.

위 그림은 두 개의 입력값을 받고, 하나의 값을 출력하는 간단한 인공신경망 (Artificial Neural Network)을 나타냅니다.

이제 TensorFlow를 이용해서 두 입력값에 대해 AND 논리 연산의 결과를 출력하는 신경망을 구현해보겠습니다.

 

훈련 데이터 준비하기

import tensorflow as tf
from tensorflow import keras
import numpy as np

tf.random.set_seed(0)

# 1. 훈련 데이터 준비하기
x_train = [[0, 0], [0, 1], [1, 0], [1, 1]]
y_train = [[0], [0], [0], [1]]

우선 tf.random 모듈의 set_seed() 함수를 사용해서 랜덤 시드를 설정했습니다.

예제에서 x_train, y_train은 각각 훈련에 사용할 입력값, 출력값입니다.

 

Neural Network 구성하기

# 2. 모델 구성하기
model = keras.Sequential([
    keras.layers.Dense(units=3, input_shape=[2], activation='relu'),
    keras.layers.Dense(units=1)
    ])

tf.keras 모듈의 Sequantial 클래스는 Neural Network의 각 층을 순서대로 쌓을 수 있도록 합니다.

tf.keras.layers 모듈의 Dense 클래스는 완전히 연결된 뉴런층을 구성합니다.

두 개의 Dense를 사용해서 아래 그림과 같은 구조의 신경망을 구성했습니다.

은닉층 (Hidden layer)의 활성화함수로 ReLU (Rectified Linear Unit)를 사용했습니다.

Neural Network 컴파일하기

# 3. 모델 컴파일하기
model.compile(loss='mse', optimizer='Adam')

손실 함수로 ‘mse’를, 옵티마이저로 ‘Adam’을 지정했습니다.

 

Neural Network 훈련하기

# 4. 모델 훈련하기
In[]
pred_before_training = model.predict(x_train)
print('Before Training: \n', pred_before_training)

history = model.fit(x_train, y_train, epochs=1000, verbose=0)

pred_after_training = model.predict(x_train)
print('After Training: \n', pred_after_training)


#Out[]
Before Training: 
 [[0.        ]
 [0.6210649 ]
 [0.06930891]
 [0.6721569 ]]
After Training: 
 [[-0.00612798]
 [ 0.00896964]
 [ 0.00497075]
 [ 0.99055475]]

tf.keras 모듈의 Model 클래스는 predict() 메서드를 포함합니다.

predict() 메서드를 이용해서 Neural Network의 예측값 (predicted value)을 얻을 수 있습니다.

Model 클래스의 fit() 메서드는 모델을 훈련하고, 훈련 진행 상황과 현재의 손실값을 반환합니다.

모델 훈련의 전후로 입력 데이터에 대한 Neural Network의 예측값을 출력하도록 했습니다.

 

손실값 확인하기

# 5. 손실값 확인하기
import matplotlib.pyplot as plt

loss = history.history['loss']
plt.plot(loss)
plt.xlabel('Epoch', labelpad=15)
plt.ylabel('Loss', labelpad=15)

plt.show()

fit() 메서드가 반환하는 손실값을 Matplotlib 라이브러리를 사용해서 시각화했습니다.

 

훈련 결과 확인하기

import matplotlib.pyplot as plt
import numpy as np

plt.style.use('default')
plt.rcParams['figure.figsize'] = (6, 4)
plt.rcParams['font.size'] = 14

plt.plot(pred_before_training, 's-', markersize=10, label='pred_before_training')
plt.plot(pred_after_training, 'd-', markersize=10, label='pred_after_training')
plt.plot(y_train, 'o-', markersize=10, label='y_train')

plt.xticks(np.arange(4), labels=['[0, 0]', '[0, 1]', '[1, 0]', '[1, 1]'])
plt.xlabel('Input (x_train)', labelpad=15)
plt.ylabel('Output (y_train)', labelpad=15)

plt.legend()
plt.show()

Matplotlib 라이브러리를 사용해서 훈련 전후의 입력값, 출력값을 나타냈습니다.

간단한 신경망에 대해 1000회의 훈련이 이루어지면, 네가지 경우의 0과 1 입력에 대해 1% 미만의 오차로

AND 연산을 수행할 수 있음을 확인할 수 있습니다.

 

전체 예제 코드

전체 코드는 아래와 같습니다.

신경망을 구성하는 과정에서 뉴런의 개수, 활성화함수, 그리고 옵티마이저를 바꿔가면서

훈련의 횟수와 정확도에 미치는 영향을 확인해 볼 수 있습니다.

import tensorflow as tf
from tensorflow import keras
import numpy as np

tf.random.set_seed(0)


# 1. 훈련 데이터 준비하기
x_train = [[0, 0], [0, 1], [1, 0], [1, 1]]
y_train = [[0], [0], [0], [1]]


# 2. 모델 구성하기
model = keras.Sequential([
    keras.layers.Dense(units=3, input_shape=[2], activation='relu'),
    # keras.layers.Dense(units=3, input_shape=[2], activation='sigmoid'),
    keras.layers.Dense(units=1)
    ])


# 3. 모델 컴파일하기
# model.compile(loss='mse', optimizer='SGD')
model.compile(loss='mse', optimizer='Adam')


# 4. 모델 훈련하기
pred_before_training = model.predict(x_train)
print('Before Training: \n', pred_before_training)

history = model.fit(x_train, y_train, epochs=1000, verbose=0)

pred_after_training = model.predict(x_train)
print('After Training: \n', pred_after_training)


# 5. 손실값 확인하기
import matplotlib.pyplot as plt

loss = history.history['loss']
plt.plot(loss)
plt.xlabel('Epoch', labelpad=15)
plt.ylabel('Loss', labelpad=15)

plt.show()

 

### 2021.12.16

 

티마이저 (Optimizer)는 손실 함수을 통해 얻은 손실값으로부터 모델을 업데이트하는 방식을 의미합니다.

TensorFlow는 SGD, Adam, RMSprop과 같은 다양한 종류의 옵티마이저를 제공합니다.

옵티마이저의 기본 사용법을 알아보고, 훈련 과정에서 옵티마이저에 따라 모델의 손실값이 어떻게 감소하는지 확인해 보겠습니다.

 

Neural Network 구성하기

이전 페이지에서와 마찬가지로 1개의 입력, 3개의 출력 노드를 갖는 신경망 모델을 구성합니다.

import tensorflow as tf
from tensorflow import keras
import numpy as np

tf.random.set_seed(0)

model = keras.Sequential([keras.layers.Dense(units=3, input_shape=[1])])

이번에는 tf.random 모듈의 set_seed() 함수를 사용해서 랜덤 시드를 설정했습니다.

tf.keras 모듈의 Sequantial 클래스는 Neural Network의 각 층을 순서대로 쌓을 수 있도록 합니다.

 

Neural Network 컴파일하기

구성한 모델의 손실 함수와 옵티마이저를 지정하기 위해 compile() 메서드를 사용합니다.

model.compile(loss='mse', optimizer='SGD')

손실 함수로 ‘mse’를, 옵티마이저로 ‘SGD’을 지정했습니다.

‘SGD’는 Stochastic Gradient Descent의 줄임말이며, 우리말로는 확률적 경사하강법이라고 부릅니다.

 

Neural Network 훈련하기

fit() 메서드는 컴파일 과정에서 지정한 손실 함수와 옵티마이저를 사용해서 모델을 훈련합니다.

In[]
model.fit([1], [[0, 1, 0]], epochs=1)
model.evaluate([1], [[0, 1, 0]])

#Out[]
1/1 [==============================] - 0s 209ms/step - loss: 1.0738
1/1 [==============================] - 0s 165ms/step - loss: 1.0453
1.0453256368637085

fit() 메서드는 훈련 진행 상황과 현재의 손실값을 반환합니다.

1회의 에포크 (epoch) 이후, evaluate() 메서드를 사용해서 손실값을 확인해보면

손실값이 1.0738에서 1.0453으로 감소했음을 알 수 있습니다.

history = model.fit([1], [[0, 1, 0]], epochs=100)

이번에는 훈련의 에포크를 100회로 지정했습니다.

100회 훈련 과정의 훈련 시간과 손실값이 출력됩니다.

 

손실값 시각화하기

import matplotlib.pyplot as plt

plt.style.use('default')
plt.rcParams['figure.figsize'] = (4, 3)
plt.rcParams['font.size'] = 12

loss = history.history['loss']
plt.plot(loss)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.show()

fit() 메서드는 History 객체를 반환합니다.

History 객체의 history 속성은 훈련 과정의 손실값 (loss values)과 지표 (metrics)를 포함합니다.

컴파일 과정에서 지표를 지정하지 않았기 때문에 이 예제의 history 속성은 지표 (metrics)를 포함하지 않습니다.

훈련 과정의 손실값을 Matplotlib을 이용해서 그래프로 나타내면 아래와 같이 감소하는 경향을 확인할 수 있습니다.

 

출력값 시각화하기

import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import numpy as np

plt.style.use('default')
plt.rcParams['figure.figsize'] = (4, 3)
plt.rcParams['font.size'] = 12

tf.random.set_seed(0)

model = keras.Sequential([keras.layers.Dense(units=3, input_shape=[1], use_bias=False)])
model.compile(loss='mse', optimizer='SGD')

pred = model.predict([1])
print(pred)
print(model.get_weights())

plt.bar(np.arange(3), pred[0])
plt.ylim(-1.1, 1.1)
plt.xlabel('Output Node')
plt.ylabel('Output')
plt.text(-0.4, 0.8, 'Epoch 0')
plt.tight_layout()
plt.savefig('./pred000.png')
plt.clf()

epochs = 500
for i in range(1, epochs+1):
  model.fit([1], [[0, 1, 0]], epochs=1, verbose=0)
  pred = model.predict([1])

  if i % 25 == 0:
      plt.bar(np.arange(3), pred[0])
      plt.ylim(-1.1, 1.1)
      plt.xlabel('Output Node')
      plt.ylabel('Output')
      plt.text(-0.4, 0.8, 'Epoch ' + str(i))
      plt.tight_layout()
      plt.savefig('./pred' + str(i).zfill(3) + '.png')
      plt.clf()

print(pred)
print(model.get_weights())
#Out[]
[[-0.5095548  -0.7187625   0.08668923]]
[array([[-0.5095548 , -0.7187625 ,  0.08668923]], dtype=float32)]
[[-0.0179761   0.9393657   0.00305823]]
[array([[-0.0179761 ,  0.9393657 ,  0.00305823]], dtype=float32)]
<Figure size 400x300 with 0 Axes>

이 코드는 Matplotlib을 이용해서 500회의 에포크 동안 훈련에 의해 출력값이 변화하는 과정을 시각화합니다.

Matplotlib의 다양한 함수에 대해서는 Matplotlib - 파이썬으로 그래프 그리기를 참고하세요.

아래 그림과 같이 훈련 과정 동안 출력값이 Target 값 [0, 1, 0]에 가까워지는 것을 알 수 있습니다.

 

옵테마이저 비교하기

아래의 예제는 세가지 옵티마이저 ‘SGD’, ‘Adam’, ‘RMSprop 이 모델을 업데이트하는 성능을 비교합니다.

import tensorflow as tf
from tensorflow import keras
import numpy as np
import matplotlib.pyplot as plt

plt.style.use('default')
plt.rcParams['figure.figsize'] = (4, 3)
plt.rcParams['font.size'] = 12

tf.random.set_seed(0)
model = keras.Sequential([keras.layers.Dense(units=3, input_shape=[1])])

tf.random.set_seed(0)
model2 = tf.keras.models.clone_model(model)

tf.random.set_seed(0)
model3 = tf.keras.models.clone_model(model)

model.compile(loss='mse', optimizer='SGD')
model2.compile(loss='mse', optimizer='Adam')
model3.compile(loss='mse', optimizer='RMSprop')

history = model.fit([1], [[0, 1, 0]], epochs=100, verbose=0)
history2 = model2.fit([1], [[0, 1, 0]], epochs=100, verbose=0)
history3 = model3.fit([1], [[0, 1, 0]], epochs=100, verbose=0)

loss = history.history['loss']
loss2 = history2.history['loss']
loss3 = history3.history['loss']
plt.plot(loss, label='SGD')
plt.plot(loss2, label='Adam')
plt.plot(loss3, label='RMSprop')
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.legend(loc='lower left')
plt.show()


# 우선 세 개의 모델이 동일한 가중치 값을 갖도록 하기 위해 **set_seed()** 함수를 세번 호출했습니다.

# **compile()** 메서드에 각각 다른 옵티마이저를 지정합니다.

100회 훈련 과정의 손실값을 시각화하면 위와 같습니다.

옵티마이저에 따라 모델을 업데이트하는 방식과 손실값이 감소하는 경향에 차이가 있음을 알 수 있습니다.

 

### 2021.12.16

손실 함수 (Loss function)는 Neural Network의 예측이 얼마나 잘 맞는지 측정하는 역할을 합니다.

손실 함수로부터 얻어진 손실값 (Loss value)은 훈련 과정에서 Neural Network가 얼마나 잘 훈련되었는지 확인하는 지표가 됩니다.

Mean Squared Error 손실 함수를 사용해서 모델의 손실값을 확인하는 과정에 대해 소개합니다.

 

Neural Network 구성하기

아래의 코드는 하나의 입력을 받고 세 개의 출력 노드를 갖는 Neural Network를 구성합니다.

import tensorflow as tf
from tensorflow import keras
import numpy as np

model = keras.Sequential([keras.layers.Dense(units=3, input_shape=[1])])

tf.keras 모듈의 Sequential 클래스는 Neural Network의 각 층을 순서대로 쌓을 수 있도록 합니다.

tf.keras.layers 모듈의 Dense 클래스는 (완전 연결된) 하나의 뉴런층을 구현합니다.

units는 뉴런 또는 출력 노드의 개수를 의미하며, 양의 정수로 설정합니다.

input_shape는 입력 데이터의 형태를 결정합니다.

 

Neural Network 컴파일하기

모델을 구성했다면, 이 모델을 훈련하기 전에 손실 함수와 옵티마이저를 지정해주는 컴파일 과정이 필요합니다.

model.compile(loss='mse')

compile() 메서드의 loss 파라미터를 이용해서 손실 함수를 'mse'로 지정했습니다.

mse Mean Squared Error의 줄임말이며 아래의 수식을 이용해서 평균 제곱 오차를 계산하는 방식입니다.

  • n은 출력값의 개수.
  • yi는 관측값 (목표값).
  • y^i는 예측값.

예측치와 관측값의 차이인 오차의 제곱에 비례해서 손실 함수로부터 계산되는 손실값이 커집니다.

 

Neural Network 예측하기

predict() 메서드를 이용해서 Neural Network의 예측값 (predicted value)을 얻을 수 있습니다.

 

in[]
pred = model.predict([0])
print(pred)

#out[]
[[0. 0. 0.]]

임의로 생성된 모델의 가중치 값 (weights)이 있지만, 입력이 0이므로 예측값도 모두 0을 출력합니다.

 

Neural Network 손실 계산하기

evaluate() 메서드는 예측값과 관측값 사이의 손실값을 반환합니다.

in[]
model.evaluate([0], [[0, 1, 0]])

#out[]
1/1 [==============================] - 0s 111ms/step - loss: 0.3333
0.3333333432674408

 

 

### 2021.12.16

Neural Network 구성하기

import tensorflow as tf
from tensorflow import keras
import numpy as np

model = keras.Sequential([keras.layers.Dense(units=1, input_shape=[1])])

tf.keras (tensorflow.keras)는 TensorFlow의 하이레벨 구현을 위한 Keras API 모듈입니다.

tf.keras 모듈의 Sequential 클래스는 Neural Network의 각 층을 순서대로 쌓을 수 있도록 합니다.

tf.keras.layers 모듈의 Dense 클래스는 (완전 연결된) 하나의 뉴런층을 구현합니다.

units는 뉴런 또는 출력 노드의 개수를 의미하며, 양의 정수로 설정합니다.

input_shape는 입력 데이터의 형태를 결정합니다.

 

Neural Network 컴파일하기

model.compile(loss='mean_squared_error', optimizer='sgd')

다음으로 Neural Network 모델을 컴파일하는 과정에서는,

모델의 학습에 필요한 손실함수 (loss function)와 옵티마이저 (optimizer)를 결정합니다.

손실함수는 Neural Network의 예측이 얼마나 잘 맞는지 측정하는 역할을 하고, 옵티마이저는 더 개선된 예측값을 출력하도록 최적화하는 알고리즘입니다.

예제에서는 각각 mean_squared_error와 SGD (Stochastic Gradient Descent)로 설정했습니다.

경우에 따라 다른 손실함수와 옵티마이저가 더 효과적일 수 있습니다.

더 자세한 내용은 TensorFlow 공식 문서를 참고하세요.

 

Neural Network 훈련하기

xs = np.array([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)
ys = np.array([-3.0, -1.0, 1.0, 3.0, 5.0, 7.0], dtype=float)

model.fit(xs, ys, epochs=500)

xs, ys는 Neural Network의 훈련에 사용할 입력과 출력 데이터이며, ‘y = 2x - 1’의 관계를 갖는 것처럼 보입니다.

에포크 (epoch)는 주어진 데이터를 한 번 훈련하는 단위입니다.

 

Neural Network 예측하기

Sequantial 클래스의 predict() 메서드를 사용하면 특정 입력에 대해 Neural Network가 출력 (예측)하는 값을 얻을 수 있습니다.

in[]
pred = model.predict([5.0])
print(pred)

#out[]
[[8.995342]]

훈련이 끝난 Neural Network에 숫자 5.0을 입력하면, 약 8.99를 출력합니다.

비록 작은 오차가 있지만, 이제 이 간단한 Neural Network는 어떤 입력 x에 대해서 대략 2x - 1를 출력하도록 훈련되었습니다.

작은 오차가 발생하는 이유는 ‘여섯 개’라는 적은 양의 입출력 데이터를 훈련에 사용했기 때문이고,

또한 모든 x에 대해, 입출력의 관계가 ‘y = 2x - 1’이 아닐 가능성이 있기 때문입니다.

전체 코드

import tensorflow as tf
from tensorflow import keras
import numpy as np

model = keras.Sequential([keras.layers.Dense(units=1, input_shape=[1])])
model.compile(optimizer='sgd', loss='mean_squared_error')

xs = np.array([-1.0, 0.0, 1.0, 2.0, 3.0, 4.0], dtype=float)
ys = np.array([-3.0, -1.0, 1.0, 3.0, 5.0, 7.0], dtype=float)

model.fit(xs, ys, epochs=500)

pred = model.predict([5.0])
print(pred)

 

 

### 2021.12.16

 

텐서란?

텐서 (Tensor)는 다차원 배열 (Multi-dimensional Array)입니다.

텐서 (Tensor)는 벡터 (Vector)와 행렬 (Matrix)을 일반화한 것이며, 3차원 이상으로 확장할 수 있습니다.

텐서 (Tensor)는 TensorFlow의 가장 주요한 객체이며, TensorFlow의 작업은 주로 텐서의 연산으로 이루어집니다.

즉, TensorFlow는 텐서 (Tensor)를 정의하고 연산을 수행하도록 하는 프레임워크 (Framework)입니다.

 

텐서의 차원 - 랭크(Rank)

텐서의 랭크 확인하기

import tensorflow as tf

scalar = tf.constant(1)
vector = tf.constant([1, 2, 3])
matrix = tf.constant([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
tensor = tf.constant([[[1, 2, 3], [4, 5, 6], [7, 8, 9],[10, 11, 12]],
                      [[1, 2, 3], [4, 5, 6], [7, 8, 9],[10, 11, 12]]])
in[]
print(tf.rank(scalar))
print(scalar)

#out[]
tf.Tensor(0, shape=(), dtype=int32)
tf.Tensor(1, shape=(), dtype=int32)
in[]
print(tf.rank(vector))
print(vector)

#out[]
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor([1 2 3], shape=(3,), dtype=int32)
in[]
print(tf.rank(matrix))
print(matrix)

#out[]
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor(
[[1 2 3]
 [4 5 6]
 [7 8 9]], shape=(3, 3), dtype=int32)
in[]
print(tf.rank(tensor))
print(tensor)

#out[]
tf.Tensor(3, shape=(), dtype=int32)
tf.Tensor(
[[[ 1  2  3]
  [ 4  5  6]
  [ 7  8  9]
  [10 11 12]]

 [[ 1  2  3]
  [ 4  5  6]
  [ 7  8  9]
  [10 11 12]]], shape=(2, 4, 3), dtype=int32)

텐서 (Tensor) 객체의 랭크 (Rank)는 차원의 수 (n-dimension)입니다.

tf.rank()는 텐서의 랭크를 반환합니다.

텐서 scalar, vector, matrix, tensor는 각각 랭크 0, 1, 2, 3를 가집니다.

 

텐서 만들기

모듈 임포트하기

import tensorflow as tf

#TensorFlow 프로그램을 만드는 가장 첫번째 단계는 tensorflow 라이브러리를 임포트하는 것입니다.

tf.constant() 사용하기

  • tf.constant()는 상수 텐서를 만듭니다.
a = tf.constant(1)
b = tf.constant([2])
c = tf.constant([[1, 2], [3, 4]])
in[1]
print(tf.rank(a))
print(a)
#out[1]
tf.Tensor(0, shape=(), dtype=int32)
tf.Tensor(1, shape=(), dtype=int32)

in[2]
print(tf.rank(b))
print(b)
#out[2]
tf.Tensor(1, shape=(), dtype=int32)
tf.Tensor([2], shape=(1,), dtype=int32)

in[3]
print(tf.rank(c))
print(c)
#out[3]
tf.Tensor(2, shape=(), dtype=int32)
tf.Tensor(
[[1 2]
 [3 4]], shape=(2, 2), dtype=int32)

 

tf.zeros() 사용하기

  • tf.zeros()는 모든 요소가 0인 텐서를 만듭니다.
  • tf.zeros()에 만들어질 텐서의 형태 (shape)를 입력합니다.
  • 텐서의 형태에 대해서는 4) 텐서의 데이터 타입과 형태를 참고하세요.
in[]
a = tf.zeros(1)
b = tf.zeros([2])
c = tf.zeros([2, 3])
print(a)
print(b)
print(c)

#out[]
tf.Tensor([0.], shape=(1,), dtype=float32)
tf.Tensor([0. 0.], shape=(2,), dtype=float32)
tf.Tensor(
[[0. 0. 0.]
 [0. 0. 0.]], shape=(2, 3), dtype=float32)

 

tf.ones() 사용하기

  • tf.ones()는 모든 요소가 1인 텐서를 만듭니다.
  • tf.ones()에 만들어질 텐서의 형태 (shape)를 입력합니다.
  • 텐서의 형태에 대해서는 4) 텐서의 데이터 타입과 형태를 참고하세요.
in[]
a = tf.ones(3)
b = tf.ones([4])
c = tf.ones([2, 2, 2])
print(a)
print(b)
print(c)

#out[]
tf.Tensor([1. 1. 1.], shape=(3,), dtype=float32)
tf.Tensor([1. 1. 1. 1.], shape=(4,), dtype=float32)
tf.Tensor(
[[[1. 1.]
  [1. 1.]]

 [[1. 1.]
  [1. 1.]]], shape=(2, 2, 2), dtype=float32)

 

tf.range() 사용하기

  • tf.range()는 파이썬 range()와 비슷하게, 주어진 범위와 간격을 갖는 숫자들의 시퀀스를 만듭니다.
in[]
a = tf.range(0, 3)
b = tf.range(1, 5, 2)
print(a)
print(b)

#out[]
tf.Tensor([0 1 2], shape=(3,), dtype=int32)
tf.Tensor([1 3], shape=(2,), dtype=int32)

 

tf.linspace() 사용하기

  • tf.linspace()는 numpy.linspace()와 비슷하게, 주어진 범위를 균일한 간격으로 나누는 숫자의 시퀀스를 반환합니다.
in[]
a = tf.linspace(0, 1, 3)
b = tf.linspace(0, 3, 10)
print(a)
print(b)

#out[]
tf.Tensor([0.  0.5 1. ], shape=(3,), dtype=float64)
tf.Tensor(
[0.         0.33333333 0.66666667 1.         1.33333333 1.66666667
 2.         2.33333333 2.66666667 3.        ], shape=(10,), dtype=float64)

 

텐서의 자료형과 형태

예제 #1

in[]
a = tf.constant(1)
b = tf.constant([2])
c = tf.constant([3, 4, 5])
print(a.dtype, a.shape)
print(b.dtype, b.shape)
print(c.dtype, c.shape)

#out[]
<dtype: 'int32'> ()
<dtype: 'int32'> (1,)
<dtype: 'int32'> (3,)

dtype, shape 속성은 각각 텐서 (Tensor)의 자료형과 형태를 반환합니다.

텐서 a, b, c는 모두 정수형 (int32)의 데이터를 갖고, 각각 ( ), (1,), (3,)의 형태를 가짐을 알 수 있습니다.

 

예제 #2

in[]
d = tf.constant([1., 2.])
e = tf.constant([[1, 2., 3]])
f = tf.constant([[1, 2], [3, 4]])
print(d.dtype, d.shape)
print(e.dtype, e.shape)
print(f.dtype, f.shape)

#out[]
<dtype: 'float32'> (2,)
<dtype: 'float32'> (1, 3)
<dtype: 'int32'> (2, 2)

텐서 d는 실수형 (float32)의 데이터를 갖고, (2,)의 형태를 가집니다.

텐서 e는 실수형 (float32)의 데이터를 갖고, (1, 3)의 형태를 가집니다.

(정수와 실수를 모두 포함하는 텐서의 자료형은 실수형이 됩니다.)

텐서 f는 정수형 (int32)의 데이터를 갖고, (2, 2)의 형태를 가집니다.

 

간단한 수학 연산

TensorFlow는 텐서 (Tensor)를 생성하고 연산하는 다양한 수학적 함수를 제공합니다.

in[]
a = tf.add(1, 2)
b = tf.subtract(10, 5)
c = tf.square(3)
d = tf.reduce_sum([1, 2, 3])
e = tf.reduce_mean([1, 2, 3])

print(a)
print(b)
print(c)
print(d)
print(e)

#out[]
tf.Tensor(3, shape=(), dtype=int32)
tf.Tensor(5, shape=(), dtype=int32)
tf.Tensor(9, shape=(), dtype=int32)
tf.Tensor(6, shape=(), dtype=int32)
tf.Tensor(2, shape=(), dtype=int32)

 

NumPy 호환성

텐서 (Tensor)는 NumPy 어레이와 비슷하지만,

  • 텐서는 GPU, TPU와 같은 가속기에서 사용할 수 있고,
  • 텐서는 값을 변경할 수 없습니다.

텐서를 NumPy array로 변경

  • 텐서의 numpy() 메서드를 사용해서 텐서를 NumPy 어레이로 변환할 수 있습니다.

 

in[]
a = tf.constant([1, 2, 3])

print(a)
print(a.numpy())

#out[]
tf.Tensor([1 2 3], shape=(3,), dtype=int32)
[1 2 3]

 

NumPy 어레이를 텐서로 변경

  • 반대로, 다양한 TensorFlow 연산은 자동으로 NumPy 어레이를 텐서로 변환합니다
in[]
import numpy as np

b = np.ones(3)

print(b)
print(tf.multiply(b, 3))


#out[]
[1. 1. 1.]
tf.Tensor([3. 3. 3.], shape=(3,), dtype=float64)

 

+ Recent posts