SW개발/머신러닝

머신러닝 스터디 2주차 - MNIST 퍼셉트론 학습 & Kaggle Competition 제출

초코쨔응 2019. 2. 21. 08:49

02/20


Python Tensorflow 연습

MNIST 퍼셉트론 학습 코드 작성




# tensorflow 패키지 불러오기

import tensorflow as tf

# 텐서플로우에서 MNIST 데이터 로드하기
from tensorflow.examples.tutorials.mnist import input_data


# 레이블이 정수 형태로 저장되어있지만 훈련을 위해서 원-핫 인코딩으로 로드해야한다.
mnist_data = input_data.read_data_sets('MNIST_data', one_hot=True)
# 퍼셉트론 입력 크기, 클래스 수, 배치 크기, 반복 또는 배치의 총 개수 선언
input_size = 784
no_classes = 10
batch_size = 100
total_batches = 200
# 입력데이터와 타깃을 위한 플레이스홀더 정의 (None은 어떤 크기든 될 수 있음을 의미)
x_input = tf.placeholder(tf.float32, shape=[None, input_size])
y_input = tf.placeholder(tf.float32, shape=[None, no_classes])
# 단순한 선형 분류자 또는 퍼셉트론을 정의
weights = tf.Variable(tf.random_normal([input_size, no_classes]))
bias = tf.Variable(tf.random_normal([no_classes]))
logits = tf.matmul(x_input, weights) + bias
# 퍼셉트론으로 생성된 로짓과 원-핫 레비을의 y_input을 비교
# 비교는 교차 엔트로피와 함께 소프트맥스를 사용
softmax_cross_entropy = tf.nn.softmax_cross_entropy_with_logits(
labels=y_input, logits=logits)
loss_operation = tf.reduce_mean(softmax_cross_entropy)
optimiser = tf.train.GradientDescentOptimizer(
learning_rate=0.5).minimize(loss_operation)
# 모델 훈련을 위한 세션 시작
session = tf.Session()
# 전역 변수 초기화 함수를 이용해 변수를 초기화
session.run(tf.global_variables_initializer())
# 배치의 데이터를 반복해서 읽고 모델을 훈련시킨다.
for batch_no in range(total_batches):
mnist_batch = mnist_data.train.next_batch(batch_size)
_, loss_value = session.run([optimiser, loss_operation], feed_dict={
x_input: mnist_batch[0],
y_input: mnist_batch[1]
})
print(loss_value)
# 정확도를 계산
predictions = tf.argmax(logits, 1)
correct_predictions = tf.equal(predictions, tf.argmax(y_input, 1))
accuracy_operation = tf.reduce_mean(tf.cast(correct_predictions, tf.float32))
test_images, test_labels = mnist_data.test.images, mnist_data.test.labels
accuracy_value = session.run(accuracy_operation, feed_dict={
x_input: test_images,
y_input: test_labels
})
print('Accuracy : ', accuracy_value)
session.close()



위 코드는 tensorflow로 import 할 수 있는 데이터 셋이었기 때문에 기본 데이터셋과 함께 제공되는 메소드를 활용하여 batch size 조절을쉽게 할 수 있었다. 하지만 Kaggle Competition에 있는 데이터 셋은 메소드를 사용할 수 없으므로 batch를 활용하지 못하고 전체 데이터로 모델을 학습 시켰다.


cf) batch와 관련된 참고 자료들

MNIST 학습 과정에서 batch training (https://3months.tistory.com/73)

Batch in deep learning (https://blog.lunit.io/2018/08/03/batch-size-in-deep-learning/)

제공 메소드 next batch 코드 내용 (https://github.com/tensorflow/tensorflow/blob/7c36309c37b04843030664cdc64aca2bb7d6ecaa/tensorflow/contrib/learn/python/learn/datasets/mnist.py#L160)



cf) softmax 모델에 대한 설명

http://solarisailab.com/archives/303




Kaggle Competition 제출울 위한 수정 코드 작성


import tensorflow as tf

#import pandas as pd

import csv


# 데이터 로드

train_data = []

train_label = []

with open('C:\\Users\\BY\\Downloads\\train.csv', 'r') as csvfile:

    csvreader = csv.reader(csvfile)

    next(csvreader) # header jump

    for row in csvreader:

        line = list(map(int, row))

        train_label.append(line[0])

        train_data.append(line[1:])

        

"""

reader = pd.read_csv('C:\\Users\\BY\\Downloads\\train.csv', header=0)

print(reader.head())

train_label = reader['label']

train_data = pd.to_numeric(reader.loc[:, 'pixel0':].values)


print(train_label.values)

print(train_data.values)

"""

# 퍼셉트론 입력 크기, 클래스 수, 배치 크기, 반복 또는 배치의 총 개수 선언

input_size = 784

no_classes = 10

batch_size = 100

total_batches = 200


# 원-핫 인코딩

# train_label_hot = tf.one_hot(train_label, no_classes)


train_label_hot = []

for row in train_label:

    for num in range(no_classes):

        if row == num:

            one_hot = [0]*no_classes

            one_hot[num] = 1

            train_label_hot.append(one_hot)


#print(train_label_hot)



# 입력데이터와 타깃을 위한 플레이스홀더 정의 (None은 어떤 크기든 될 수 있음을 의미)

x_input = tf.placeholder(tf.float32, shape=[None, input_size])

y_input = tf.placeholder(tf.float32, shape=[None, no_classes])


# 단순한 선형 분류자 또는 퍼셉트론을 정의

weights = tf.Variable(tf.random_normal([input_size, no_classes]))

bias = tf.Variable(tf.random_normal([no_classes]))

logits = tf.matmul(x_input, weights) + bias


# 퍼셉트론으로 생성된 로짓과 원-핫 레비을의 y_input을 비교

# 비교는 교차 엔트로피와 함께 소프트맥스를 사용

softmax_cross_entropy = tf.nn.softmax_cross_entropy_with_logits(

    labels=y_input, logits=logits)

loss_operation = tf.reduce_mean(softmax_cross_entropy)

optimiser = tf.train.GradientDescentOptimizer(

    learning_rate=0.5).minimize(loss_operation)


# 모델 훈련을 위한 세션 시작

session = tf.Session()


# 전역 변수 초기화 함수를 이용해 변수를 초기화

session.run(tf.global_variables_initializer())

print(len(train_data))

print(len(train_label_hot))


_, loss_value = session.run([optimiser, loss_operation], feed_dict={

    x_input: train_data,

    y_input: train_label_hot

})

    print(loss_value)


# test 데이터 불러오기

# 데이터 로드

test_daa = []

with open('C:\\Users\\BY\\Downloads\\test.csv', 'r') as csvfile:

    csvreader = csv.reader(csvfile)

    next(csvreader) # header jump

    for row in csvreader:

        test_data.append(list(map(int, row)))

        

#test_data = pd.read_csv('C:\\Users\\BY\\Downloads\\test.csv', header=0)


# 정확도를 계산

predictions = tf.argmax(logits, 1)

test_label = session.run([predictions], feed_dict={

    x_input: test_data

})


# with open

# f_result.write("" %())


with open('C:\\Users\\BY\\Downloads\\submission.csv', mode='w', newline='\n') as csvfile:

    tensor_result = csv.writer(csvfile, delimiter=',')

    tensor_result.writerow(['ImageId', 'Label'])

    for line in range(len(test_label[0])):

        tensor_result.writerow([str(line+1), str(test_label[0][line])])


#print('test_label : ', test_label[0])

session.close()



주어진 csv 파일을 다운 받아서 불러와서 모델을 학습시키는 코드를 작성하였다. 또한 test용 csv 파일도 불러와서 결과물을 csv 파일로 저장하도록 했다. (꼭 칼럼 이름을 Kaggle에서 지정한 것으로 첫 행에 적어줘야 한다! 그렇지 않으면 채점에 실패한다.) Kaggle에 결과물로 저장된 csv 파일을 제출한다.


cf)

session에서 prediction 결과를 뽑아내는 코드 (https://github.com/tensorflow/tensorflow/issues/97) - 원래 교재 제공 코드는 test input에 대해 prediction label을 뽑아내는 것이 아니라 정해진 test output을 가지고 accuracy를 바로 계산하도록 되어있었다.


cf)

python에서 csv read와 write 코드 참고 (https://realpython.com/python-csv/)




Kaggle Competition 제출 결과



prediction이 엄청나게 낮아서 거의 학습이 안 되었음에도 불구하고 꼴등이 아니었다....ㅠㅠ

반응형