SVHN

ro_ot ㅣ 2020. 1. 31. 17:28

image 3개 

%tensorflow_version 2.0x
import tensorflow as tf
from tensorflow import keras
from google.colab import files
# 구글 드라이브에 파일을 업로드해두고 읽는 방식
from google.colab import drive
drive.mount('/content/drive')
import numpy as np
from scipy.io import loadmat
import matplotlib.pyplot as plt
import os
os.chdir('drive/My Drive/Colab Notebooks')
mat = loadmat('test_32x32.mat')
mat.keys()
# 데이터 획득
x = mat['X']
y = mat['y']
x.shape, y.shape
# 전처리
x = np.transpose(x, [3,0,1,2])/255
y = y[:, 0]
x.shape, y.shape, np.max(x)
# y 에서 10값을 0으로 바꾸기
y = np.where(y > 9, 0, y)
set(y)
m = len(y)//2
x_train = x[:m]
y_train = y[:m]
x_test = x[m:m*2]
y_test = y[m:m*2]
def attach_3_image(x, y):
  #x (m,h,w,c), y (m)
  m = len(y)
  m = m - m % 3
  x = x[:m]
  y = y[:m] # 3의 배수의 데이터수 사용
  pad = 6
  x = x [:,:, pad:-pad]

  x_0 = x[::3]
  x_1 = x[1::3]
  x_2 = x[2::3]
  x_attach = np.concatenate((x_0, x_1, x_2), axis=2)
  y_attach = np.reshape(y, [-1, 3])
  return x_attach, y_attach
x3_train, y3_train = attach_3_image(x_train, y_train)
x3_test, y3_test = attach_3_image(x_test, y_test)
x_train.shape, y3_train.shape, x3_test.shape, y3_test.shape
i = 3
plt.title(str(y3_train[i]))
plt.imshow(x3_train[i])

class MyModel(keras.Model): # github.com/sogangori/choongang20/ 
  def __init__(self):    
    super(MyModel, self).__init__()
    self.k = 10
    self.opt = tf.optimizers.RMSprop(learning_rate=0.01)#Stochatic Gradient Descent 확률적 경사 하강
    self.conv0 = keras.layers.Conv2D(16, [3,3], padding='same', activation=keras.activations.relu)
    self.conv1 = keras.layers.Conv2D(16, [3,3], padding='same', activation=keras.activations.relu)
    self.conv2 = keras.layers.Conv2D(16, [3,3], padding='same', activation=keras.activations.relu)
    self.conv3 = keras.layers.Conv2D(16, [3,3], padding='same', activation=keras.activations.relu)
    self.pool0 = keras.layers.MaxPool2D([2,2], padding='same')
    self.pool1 = keras.layers.MaxPool2D([2,2], padding='same')
    self.flatten = keras.layers.Flatten()
    self.dense = keras.layers.Dense(units=self.k)
  
  def call(self, x):
    x = tf.cast(x, tf.float32)
    net = self.conv0(x)
    net = self.pool0(net)
    net = self.conv1(net)
    net = self.pool1(net)
    net = self.conv2(net)
    net = self.pool1(net)
    net = self.conv3(net)
    net = self.pool1(net)
    net = self.flatten(net)    
    h = self.dense(net)
    h = tf.nn.softmax(h, axis=1)
    return h

  def get_loss(self, y, h):
    #학습할때 nan이 발생하는 경우 값을 clip(자르다) (최소값, 최대값) 
    h = tf.clip_by_value(h, 1e-8, 1 - 1e-8) # h 가 0이나 1이 되지 않도록 하는 안전장치 
    #cross_entropy = - (y * tf.math.log(h) + (1 - y) * tf.math.log(1 - h)) 
    cross_entropy = - (y * tf.math.log(h)) 
    loss = tf.reduce_mean(cross_entropy)
    return loss

  def get_accuracy(self, y, h):    
    predict = tf.argmax(h, -1)
    is_equal = tf.equal(y, predict)
    self.acc = tf.reduce_mean(tf.cast(is_equal, tf.float32)) # True > 1, False > 0 로 cast

  def fit(self, x, y, epoch=1):
    y_hot = tf.one_hot(y, depth=self.k, axis=-1)
    for i in range(epoch):
      with tf.GradientTape() as tape: #경사 기록 장치
        h = self.call(x)
        loss = self.get_loss(y_hot, h)        
      grads = tape.gradient(loss, self.trainable_variables) #경사 계산
      #경사가 너무 크면 nan 이 될 수 있으므로 gradient cliping (최소,최대값 제한) 을 합니다
      grads = [(tf.clip_by_value(grad, -8.0, 8.0)) for grad in grads]      
      self.opt.apply_gradients(zip(grads, self.trainable_variables)) # 가중치에서 경사를 빼기
      self.get_accuracy(y, h)
      
      if i%10==0:
        print('%d/%d loss:%.3f acc:%.3f acc_all:%.3f'%(i, epoch, loss, self.acc, acc_all))
model = MyModel()
model.fit(x[:500], y[:500], epoch=1000)

'Deep learning > Code' 카테고리의 다른 글

.mat 파일 읽어오기  (0) 2020.01.31
numtest  (0) 2020.01.31
rnn_2_number_with_blank  (0) 2020.01.30
cnn_2_number_with_blank  (0) 2020.01.30
cnn_2_number  (0) 2020.01.30