728x90
반응형
728x170
■ 얼굴 감정을 판정하는 컨볼루션 신경망을 만드는 방법을 보여준다.
※ 첨부 소스 코드를 특정 폴더에 압축을 풀고, EmotionDetector.py를 실행해 데이터를 학습하고, TestEmotion.py를 실행해 샘플 이미지를 테스트 한다.
SourceCode.zip
9.91MB
SourceCode.z01
19.53MB
▶ EmotionHelper.py
import numpy as np
import os
import pandas as pd
import six.moves.cPickle as pickle
IMAGE_SIZE = 48
OUTPUT_COUNT = 7
VALIDATION_PERCENT = 0.1
np.random.seed(0)
class EmotionResult:
def __init__(self):
self.anger = 0
self.disgust = 0
self.fear = 0
self.happy = 0
self.sad = 0
self.surprise = 0
self.neutral = 0
def Evaluate(self, label):
if (0 == label): self.anger = self.anger + 1
if (1 == label): self.disgust = self.disgust + 1
if (2 == label): self.fear = self.fear + 1
if (3 == label): self.happy = self.happy + 1
if (4 == label): self.sad = self.sad + 1
if (5 == label): self.surprise = self.surprise + 1
if (6 == label): self.neutral = self.neutral + 1
def DisplayResult(self, totalScore):
print("분노 = " + str((self.anger / float(totalScore)) * 100) + "%")
print("혐오 = " + str((self.disgust / float(totalScore)) * 100) + "%")
print("공포 = " + str((self.fear / float(totalScore)) * 100) + "%")
print("행복 = " + str((self.happy / float(totalScore)) * 100) + "%")
print("슬픔 = " + str((self.sad / float(totalScore)) * 100) + "%")
print("놀람 = " + str((self.surprise / float(totalScore)) * 100) + "%")
print("중립 = " + str((self.neutral / float(totalScore)) * 100) + "%")
def ReadData(sourceDirectoryPath, force = False):
def CreateOneHotLabel(x):
labelNDArray = np.zeros((1, OUTPUT_COUNT), dtype = np.float32)
labelNDArray[:, int(x)] = 1
return labelNDArray
pickleFilePath = os.path.join(sourceDirectoryPath, "EmotionDetector.pickle")
if force or not os.path.exists(pickleFilePath):
trainFilePath = os.path.join(sourceDirectoryPath, "train.csv")
dataFrame = pd.read_csv(trainFilePath)
dataFrame["Pixels"] = dataFrame["Pixels"].apply(lambda x: np.fromstring(x, sep = " ") / 255.0)
dataFrame = dataFrame.dropna()
print("train.csv 파일을 읽고 있습니다...")
trainImageNDArray = np.vstack(dataFrame["Pixels"]).reshape(-1, IMAGE_SIZE, IMAGE_SIZE, 1)
print(trainImageNDArray.shape)
trainLabelNDArray = np.array(list(map(CreateOneHotLabel, dataFrame["Emotion"].values))).reshape(-1, OUTPUT_COUNT)
print(trainLabelNDArray.shape)
permutations = np.random.permutation(trainImageNDArray.shape[0])
trainImageNDArray = trainImageNDArray[permutations]
trainLabelNDArray = trainLabelNDArray[permutations]
validationIndex = int(trainImageNDArray.shape[0] * VALIDATION_PERCENT)
validImageNDArray = trainImageNDArray[:validationIndex]
validLabelNDArray = trainLabelNDArray[:validationIndex]
trainImageNDArray = trainImageNDArray[validationIndex:]
trainLabelNDArray = trainLabelNDArray[validationIndex:]
print("test.csv 파일을 읽고 있습니다...")
testFilePath = os.path.join(sourceDirectoryPath, "test.csv")
dataFrame = pd.read_csv(testFilePath)
dataFrame["Pixels"] = dataFrame["Pixels"].apply(lambda x: np.fromstring(x, sep = " ") / 255.0)
dataFrame = dataFrame.dropna()
testImageNDArray = np.vstack(dataFrame['Pixels']).reshape(-1, IMAGE_SIZE, IMAGE_SIZE, 1)
with open(pickleFilePath, "wb") as file:
try:
print("파일을 직렬화하고 있습니다...")
saveDictionary = {
"trainImageNDArray" : trainImageNDArray,
"trainLabelNDArray" : trainLabelNDArray,
"validImageNDArray" : validImageNDArray,
"validLabelNDArray" : validLabelNDArray,
"testImageNDArray" : testImageNDArray,
}
pickle.dump(saveDictionary, file, pickle.HIGHEST_PROTOCOL)
except:
print("파일을 직렬화할 수 없습니다.")
with open(pickleFilePath, "rb") as file:
saveDictionary = pickle.load(file)
trainImageNDArray = saveDictionary["trainImageNDArray"]
trainLabelNDArray = saveDictionary["trainLabelNDArray"]
validImageNDArray = saveDictionary["validImageNDArray"]
validLabelNDArray = saveDictionary["validLabelNDArray"]
testImageNDArray = saveDictionary["testImageNDArray" ]
return trainImageNDArray, trainLabelNDArray, validImageNDArray, validLabelNDArray, testImageNDArray
▶ EmotionDetector.py
import tensorflow as tf
import numpy as np
import time
import EmotionHelper
dataDirectoryPath = "data/"
logDirectoryPath = "log/"
BATCH_SIZE = 128
LEARNING_RATIO = 0.001
EPOCH_COUNT = 1000
REGULARIZATION = 0.001
IMAGE_SIZE = 48
OUTPUT_COUNT = 7
def GetNextBatchData(sourceImageNDArray, sourceLabelNDArray, epoch):
offset = (epoch * BATCH_SIZE) % (sourceImageNDArray.shape[0] - BATCH_SIZE)
batchInputNDArray = sourceImageNDArray[offset:offset + BATCH_SIZE]
batchRightOutputNDArray = sourceLabelNDArray[offset:offset + BATCH_SIZE]
return batchInputNDArray, batchRightOutputNDArray
# 학습 데이터 등을 로드한다.
trainImageNDArray, trainLabelNDArray, validImageNDArray, validLabelNDArray, testImageNDArray = EmotionHelper.ReadData(dataDirectoryPath)
print("학습 데이터 크기 : %s" % trainImageNDArray.shape[0])
print('검증 데이터 크기 : %s' % validImageNDArray.shape[0])
print("테스트 데이터 크기 : %s" % testImageNDArray.shape[0])
# 가중치를 정의한다.
convolutionLayer1WeightVariable = tf.get_variable("convolutionLayer1Weight" , initializer = tf.truncated_normal([5, 5, 1, 32], stddev = 0.02))
convolutionLayer2WeightVariable = tf.get_variable("convolutionLayer2Weight" , initializer = tf.truncated_normal([3, 3, 32, 64], stddev = 0.02))
fullyConntectedLayer1WeightVariable = tf.get_variable("fullyConntectedLayer1Weight", initializer = tf.truncated_normal([(IMAGE_SIZE // 4) * (IMAGE_SIZE // 4) * 64, 256], stddev = 0.02))
outputLayerWeightVariable = tf.get_variable("outputLayerWeight" , initializer = tf.truncated_normal([256, OUTPUT_COUNT], stddev = 0.02))
# 바이어스를 정의한다.
convolutionLayer1BiasVariable = tf.get_variable("convolutionLayer1Bias" , initializer = tf.constant(0.0, shape = [32]))
convolutionLayer2BiasVariable = tf.get_variable("convolutionLayer2Bias" , initializer = tf.constant(0.0, shape = [64]))
fullyConnectedLayer1BiasVariable = tf.get_variable("fullyConnectedLayer1Bias", initializer = tf.constant(0.0, shape = [256]))
outputLayerBiasVariable = tf.get_variable("outputLayerBias" , initializer = tf.constant(0.0, shape = [OUTPUT_COUNT]))
# 모델을 정의한다.
globalStepVariable = tf.Variable(0, trainable = False)
inputTensor = tf.placeholder(tf.float32, [None, IMAGE_SIZE, IMAGE_SIZE, 1], name = "input")
rightOutputTensor = tf.placeholder(tf.float32, [None, OUTPUT_COUNT])
# 컨볼루션 레이어 #1을 정의한다.
tf.summary.histogram("convolutionLayer1Weight", convolutionLayer1WeightVariable)
tf.summary.histogram("convolutionLayer1Bias" , convolutionLayer1BiasVariable )
convolutionLayer1OutputTensor = tf.nn.conv2d(inputTensor, convolutionLayer1WeightVariable, strides = [1, 1, 1, 1], padding = "SAME")
convolutionLayer1OutputTensorBias = tf.nn.bias_add(convolutionLayer1OutputTensor, convolutionLayer1BiasVariable)
convolutionLayer1OutputTensorReLU = tf.nn.relu(convolutionLayer1OutputTensorBias)
convolutionLayer1OutputTensorMaxPool = tf.nn.max_pool(convolutionLayer1OutputTensorReLU, ksize = [1, 2, 2, 1], strides = [1, 2, 2, 1], padding = "SAME")
tf.add_to_collection("loss", tf.nn.l2_loss(convolutionLayer1WeightVariable))
tf.add_to_collection("loss", tf.nn.l2_loss(convolutionLayer1BiasVariable ))
# 컨볼루션 레이어 #2를 정의한다.
tf.summary.histogram("convolutionLayer2Weight", convolutionLayer2WeightVariable)
tf.summary.histogram("convolutionLayer2Bias" , convolutionLayer2BiasVariable )
convolutionLayer2OutputTensor = tf.nn.conv2d(convolutionLayer1OutputTensorMaxPool, convolutionLayer2WeightVariable, strides = [1, 1, 1, 1], padding = "SAME")
convolutionLayer2OutputTensorBias = tf.nn.bias_add(convolutionLayer2OutputTensor, convolutionLayer2BiasVariable)
convolutionLayer2OutputTensorReLU = tf.nn.relu(convolutionLayer2OutputTensorBias)
convolutionLayer2OutputTensorMaxPool = tf.nn.max_pool(convolutionLayer2OutputTensorReLU, ksize = [1, 2, 2, 1], strides = [1, 2, 2, 1], padding = "SAME")
tf.add_to_collection("loss", tf.nn.l2_loss(convolutionLayer2WeightVariable))
tf.add_to_collection("loss", tf.nn.l2_loss(convolutionLayer2BiasVariable ))
# 전 연결층 레이어 #1을 정의한다.
tf.summary.histogram("fullyConntectedLayer1Weight", fullyConntectedLayer1WeightVariable)
tf.summary.histogram("fullyConnectedLayer1Bias" , fullyConnectedLayer1BiasVariable )
fullyConnectedLayer1OutputTensor = tf.reshape(convolutionLayer2OutputTensorMaxPool, [-1, (IMAGE_SIZE // 4) * (IMAGE_SIZE // 4) * 64])
fullyConnectedLayer1OutputTensorReLU = tf.nn.relu(tf.matmul(fullyConnectedLayer1OutputTensor, fullyConntectedLayer1WeightVariable) + fullyConnectedLayer1BiasVariable)
fullyConnectedLayer1OutputTensorDropout = tf.nn.dropout(fullyConnectedLayer1OutputTensorReLU, 0.5)
# 출력 레이어를 정의한다.
tf.summary.histogram("outputLayerWeight", outputLayerWeightVariable)
tf.summary.histogram("outputLayerBias" , outputLayerBiasVariable )
outputLayerTensor = tf.matmul(fullyConnectedLayer1OutputTensorDropout, outputLayerWeightVariable) + outputLayerBiasVariable
outputTensor = tf.nn.softmax(outputLayerTensor, name = "output")
# 비용 함수를 정의한다.
costTensor = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits = outputLayerTensor, labels = rightOutputTensor))
tf.summary.scalar("cost", costTensor)
regularizationLossTensor = tf.add_n(tf.get_collection("loss"))
tf.summary.scalar("regularizationLoss", regularizationLossTensor)
lossTensor = costTensor + REGULARIZATION * regularizationLossTensor
# 옵티마이저를 정의한다.
optimizerOperation = tf.train.AdamOptimizer(LEARNING_RATIO).minimize(lossTensor, global_step = globalStepVariable)
# 데이터를 학습한다.
summaryTensorp = tf.summary.merge_all()
with tf.Session() as session:
session.run(tf.global_variables_initializer())
fileWriter = tf.summary.FileWriter(logDirectoryPath, session.graph)
saver = tf.train.Saver()
checkpointStatue = tf.train.get_checkpoint_state(logDirectoryPath)
if checkpointStatue and checkpointStatue.model_checkpoint_path:
saver.restore(session, checkpointStatue.model_checkpoint_path)
print("모델이 복구되었습니다...")
for epoch in range(EPOCH_COUNT + 1):
batchInputNDArray, batchRightOutputNDArray = GetNextBatchData(trainImageNDArray, trainLabelNDArray, epoch)
session.run(optimizerOperation, feed_dict = {inputTensor : batchInputNDArray, rightOutputTensor : batchRightOutputNDArray})
if epoch % 10 == 0:
loss, summary = session.run([lossTensor, summaryTensorp], feed_dict = {inputTensor : batchInputNDArray, rightOutputTensor : batchRightOutputNDArray})
fileWriter.add_summary(summary, global_step = epoch)
print("훈련 손실 : %f" % loss)
if epoch % 100 == 0:
loss = session.run(lossTensor, feed_dict = {inputTensor : validImageNDArray, rightOutputTensor : validLabelNDArray})
print("%s 검증 손실 : %f" % (time.strftime("%X", time.localtime(time.time())), loss))
saver.save(session, logDirectoryPath + "model.ckpt", global_step = epoch)
▶ TestEmotion.py
import matplotlib.image as img
import matplotlib.pyplot as pp
import numpy as np
import tensorflow as tf
import EmotionHelper
# 소스 이미지를 로드합니다.
sourceImageNDArray = img.imread("source.jpg")
grayscaleImageNDArray = np.dot(sourceImageNDArray[...,:3], [0.299, 0.587, 0.114])
inputImageNDArray = np.resize(grayscaleImageNDArray, (1, 48, 48, 1))
pp.imshow(grayscaleImageNDArray, cmap = pp.get_cmap("gray"))
pp.show()
# 신경망 모델 데이터를 로드합니다.
session = tf.InteractiveSession()
saver = tf.train.import_meta_graph("log/model.ckpt-1000.meta")
saver.restore(session, "log/model.ckpt-1000")
tf.get_default_graph().as_graph_def()
inputTensor = session.graph.get_tensor_by_name("input:0" )
outputTensor = session.graph.get_tensor_by_name("output:0")
# 얼굴 감정을 평가합니다.
emotionResult = EmotionHelper.EmotionResult()
evaluationCount = 1000
for i in range(0, evaluationCount):
outputNDArray = session.run(outputTensor, feed_dict = {inputTensor : inputImageNDArray})
output = session.run(tf.argmax(outputNDArray, 1))
output = output[0]
output = int(output)
emotionResult.Evaluate(output)
emotionResult.DisplayResult(evaluationCount)
728x90
반응형
그리드형(광고전용)
'Python > tensorflow' 카테고리의 다른 글
[PYTHON/TENSORFLOW] 양방향 순환 신경망 만들기 (MNIST) (0) | 2018.08.13 |
---|---|
[PYTHON/TENSORFLOW] 순환 신경망 만들기 (MNIST) (0) | 2018.08.13 |
[PYTHON/TENSORFLOW] 컨볼루션 오토 인코더 만들기 (0) | 2018.08.10 |
[PYTHON/TENSORFLOW] 노이즈 제거 오토 인코더 만들기 (0) | 2018.08.07 |
[PYTHON/TENSORFLOW] 오토 인코더 만들기 (0) | 2018.08.07 |
[PYTHON/TENSORFLOW] 컨볼루션 신경망 만들기 (MNIST) (0) | 2018.08.04 |
[PYTHON/TENSORFLOW] 컨볼루션 신경망 만들기 (MNIST) (0) | 2018.08.03 |
[PYTHON/TENSORFLOW] 다층 퍼셉트론 신경망 만들기 (MNIST) : 4계층 ReLU Dropout 1계층 Softmax (0) | 2018.08.01 |
[PYTHON/TENSORFLOW] 다층 퍼셉트론 신경망 만들기 (MNIST) : 4계층 ReLU 1계층 Softmax (0) | 2018.08.01 |
[PYTHON/TENSORFLOW] 다층 퍼셉트론 신경망 만들기 (MNIST) : 4계층 Sigmoid 1계층 Softmax (0) | 2018.08.01 |
댓글을 달아 주세요