На основе материала https://www.tensorflow.org/tutorials/image_retraining потренируем нейросеть для распознавания эмоций. Фотографии эмоций, разделенные на несколько подгрупп (злость, отвращение, слезы, счастье, удрученность, удивление, нейтральность) хранятся в csv файле ( в первом столбце – номер эмоции по порядку (от 0 до 6), во втором – 48х48 пикселей картинка в сером цвете (биты 0-255)).
Преобразовать в jpg файлы можно программой Python
#! /usr/bin/env # -*-coding: utf-8-*- __author__ = 'fer_2013' import numpy as np import cv2 import mxnet as mx import pandas as pd import random import os curdir = os.path.abspath(os.path.dirname(__file__)) def gen_record(csvfile,channel): data = pd.read_csv(csvfile,delimiter=',',dtype='a') labels = np.array(data['emotion'],np.float) # print(labels,'\n',data['emotion']) imagebuffer = np.array(data['pixels']) images = np.array([np.fromstring(image,np.uint8,sep=' ') for image in imagebuffer]) del imagebuffer num_shape = int(np.sqrt(images.shape[-1])) images.shape = (images.shape[0],num_shape,num_shape) # img=images[0];cv2.imshow('test',img);cv2.waitKey(0);cv2.destroyAllWindow();exit() dirs = set(data['Usage']) subdirs = set(labels) class_dir = {} for dr in dirs: dest = os.path.join(curdir,dr) class_dir[dr] = dest if not os.path.exists(dest): os.mkdir(dest) data = zip(labels,images,data['Usage']) for d in data: destdir = os.path.join(class_dir[d[-1]],str(int(d[0]))) if not os.path.exists(destdir): os.mkdir(destdir) img = d[1] filepath = unique_name(destdir,d[-1]) print('[^_^] Write image to %s' % filepath) if not filepath: continue sig = cv2.imwrite(filepath,img) if not sig: print('Error') exit(-1) def unique_name(pardir,prefix,suffix='jpg'): filename = '{0}_{1}.{2}'.format(prefix,random.randint(1,10**8),suffix) filepath = os.path.join(pardir,filename) if not os.path.exists(filepath): return filepath unique_name(pardir,prefix,suffix) if __name__ == '__main__': filename = 'fer2013.csv' filename = os.path.join(curdir,filename) gen_record(filename,1) # ##################### test # tmp = unique_name('./Training','Training') # print(tmp)
После преобразования переименовываем директории 0-6 в англоязычные (angry, disgust, … neutral).
создаем еще одно виртуальное окружение virtualenv ( мое название - tensorflow)
$ virtualenv ~/.virtualenvs/tensorflow
Заходим $ source ~/.virtualenvs/tensorflow/bin/activate
Устанавливаем Bazel https://bazel.build/versions/master/docs/install-ubuntu.html
были проблемы с jre но установка из исходников помогла. Также пришлось поставить mock $pip install mock
Моя директория установленными примерами tensorflow выглядит так (клонирована гитом с https://github.com/tensorflow/tensorflow):
Поэтому для того, чтобы зайти в директорию для запуска bazel необходимо выполнить $ cd tf/tensorflow
Если это первый запуск после установки – не забудьте сконфигурировать ./configure !!!!!!
Запускаем bazel для создания исполняемого файла $ bazel build tensorflow/examples/image_retraining1:retrain
перед этим неплохо установить необходимые библиотеки $ sudo apt-get install python-numpy python-scipy python-matplotlib ipython ipython-notebook python-pandas python-sympy python-nose
Я сделал дубликат пример image_retrain для дальнейшей модификации и назвал его image_retrain1 (скопировал папку с примером).
Создание исполняемого файла на моей машине (ntel® Core™ i3-4160 CPU @ 3.60GHz ? 4 6Gb) занимает примерно 30 минут. Надо бы задействовать установленную на машине NVidia GT720 2Mb для вычислений…
Затем запускаем собственно тренировку нейросети. В моем случае:
$bazel-bin/tensorflow/examples/image_retraining1/retrain --image_dir ~/fer2013/training1
В директории ~/fer2013/training1 содержатся папки (angry, disgust, fear,… neutral) с графическими файлами внутри.
нейросеть тренировалась примерно 3 часа ( больше всего времени было потрачено на создание bottleneck файлов – но точность получилась как в анекдоте – 50/50…
Тестирование результата получившейся нейросети можно с использованием программы eldor4do https://github.com/eldor4do/TensorFlow-Examples/blob/master/retraining-example.py
Она показалась мне более простой и понятной.
""" Preparing model: - Install bazel ( check tensorflow's github for more info ) Ubuntu 14.04: - Requirements: sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install oracle-java8-installer - Download bazel, ( https://github.com/bazelbuild/bazel/releases ) tested on: https://github.com/bazelbuild/bazel/releases/download/0.2.0/bazel-0.2.0-jdk7-installer-linux-x86_64.sh - chmod +x PATH_TO_INSTALL.SH - ./PATH_TO_INSTALL.SH --user - Place bazel onto path ( exact path to store shown in the output) - For retraining, prepare folder structure as - root_folder_name - class 1 - file1 - file2 - class 2 - file1 - file2 - Clone tensorflow - Go to root of tensorflow - bazel build tensorflow/examples/image_retraining:retrain - bazel-bin/tensorflow/examples/image_retraining/retrain --image_dir /path/to/root_folder_name --output_graph /path/output_graph.pb --output_labels /path/output_labels.txt --bottleneck_dir /path/bottleneck ** Training done. ** For testing through bazel, bazel build tensorflow/examples/label_image:label_image && \ bazel-bin/tensorflow/examples/label_image/label_image \ --graph=/path/output_graph.pb --labels=/path/output_labels.txt \ --output_layer=final_result \ --image=/path/to/test/image For testing through python, change and run this code. """ import numpy as np import tensorflow as tf imagePath = '/tmp/imagenet/neutral1.jpg' modelFullPath = '/tmp/output_graph.pb' labelsFullPath = '/tmp/output_labels.txt' def create_graph(): """Creates a graph from saved GraphDef file and returns a saver.""" # Creates graph from saved graph_def.pb. with tf.gfile.FastGFile(modelFullPath, 'rb') as f: graph_def = tf.GraphDef() graph_def.ParseFromString(f.read()) _ = tf.import_graph_def(graph_def, name='') def run_inference_on_image(): answer = None if not tf.gfile.Exists(imagePath): tf.logging.fatal('File does not exist %s', imagePath) return answer image_data = tf.gfile.FastGFile(imagePath, 'rb').read() # Creates graph from saved GraphDef. create_graph() with tf.Session() as sess: softmax_tensor = sess.graph.get_tensor_by_name('final_result:0') predictions = sess.run(softmax_tensor, {'DecodeJpeg/contents:0': image_data}) predictions = np.squeeze(predictions) top_k = predictions.argsort()[-5:][::-1] # Getting top 5 predictions f = open(labelsFullPath, 'rb') lines = f.readlines() labels = [str(w).replace("\n", "") for w in lines] for node_id in top_k: human_string = labels[node_id] score = predictions[node_id] print('%s (score = %.5f)' % (human_string, score)) answer = labels[top_k[0]] return answer if __name__ == '__main__': run_inference_on_image()