Az Entrópia Samu projekt célja a mesterséges intelligencia megteremtése... ennyi, nem kell cifrázni :)
Hogyan? Egy új, kifejlesztendő e-sport eredményeképpen... ez lesz az ESAMU, részletek az Entrópia Samu Programozói Kézikönyvben, ami tk. ennek az e-sportnak az előzetes sw követelményeit specifikálja. Az első implementációs gyors protó az Arccsata. Az ESAMU e-sport(ok)nak a játszható felülete a "Gréta, az építő" program, amelynek jelen pillanatban egy And-os implementációja készül. Ennek feladata, hogy a Face Battle ESAMU implementáció TensorFlow (TF, Google DeepMind) alapú arcfelismerő megoldására olyan TF gráfszerkesztőként funkcionáljon, amely a felhasználók felé játékként tud megjelenni.
Ebben a posztban a TF-hez adunk egy kis bevezetést. Nyilván első lépés a TF sikeres telepítése... illetve lásd a kapcsolódó előadást: https://prezi.com/0u8ncvvoabcr/no-programming-programming/
TensorFlow Hello World 1!
Ha megvagy a telepítéssel, találkozzunk a TF repóban, itt:
nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/twicetwo
ahol a twicetwo könyvtárat már Te hozod létre és kezdjük ennek a kis Python proginak a futtatását. Miért Python? Mert a TF C++ interfésze fejletlen, a számítási gráfokat Python kóddal építjük, majd egy protobuf szerializált gráfot töltönk az arcfelismerő Arccsata C++ Boost-os szerverbe (a "Samu, az agyba"-ba) de még nem ma! Most pár "Helló, Világ!" jellegű példával kezdjük az ismerkedést.
Jöjjön az első Python kód, ezt a nyelv szempontjából magyarázni/tanulni nem kell, hiszen éppen ez az a fícsör, amiért a Python létezik :) Akinek ez lesz az első Python kódja annyit kell tudni, hogy az Algol behozta blokkstruktúra itt nem nyitó és záró tagokkal (begin-end vagy kapcsos zárójelek) hanem a behúzással van megszervezve, azaz az ugyanoda tabulált egymás alatti sorok alkotják a blokkot. Akinek pedig mégis igénye egy kis Python nyelvi bevezetőre, annak a Forstner Bertalan, Ekler Péter, Kelényi Imre: Bevezetés a mobilprogramozásba. Gyors prototípus-fejlesztés Python és Java nyelven c. könyvet ajánlom, amelyben van olyan 10 oldal általános bevezető, ha ezt elolvassa, akkor sok időt megspórolva máris többet tud a Pythonból mint kéne.
twicetwo.py
# # TensorFlow Hello World 1! # twicetwo.py # import tensorflow node1 = tensorflow.constant(2) node2 = tensorflow.constant(2) node_twicetwo = tensorflow.mul(node1, node2, name="twicetwo") sess = tensorflow.Session() print sess.run(node_twicetwo) writer = tensorflow.train.SummaryWriter("/tmp/twicetwo", sess.graph) # nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/tensorboard$ python tensorboard.py --logdir=/tmp/twicetwo tensorflow.train.write_graph(sess.graph_def, "models/", "twicetwo.pb", as_text=False) # nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/twicetwo$ bazel build :twicetwo # nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/twicetwo$ cp -r ~/Robopsychology/repos/tensorflow/tensorflow/twicetwo/models .
Nem túl látványos igaz? Kiszámoljuk, hogy 2*2 az 4:
nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/twicetwo$ python twicetwo.py
4
és valóban kijött. Lássuk a ezt a számítást elvégző számítási gráfot a Tensorboard-ban:
nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/tensorboard$ python tensorboard.py --logdir=/tmp/twicetwo
itt megsasolhatjuk, hogy fest a Tensorboard-ba betöltött számítási gráf, amelyet az iménti a Python forráskód felépített:Vessük össze a Python kóddal: van két konstans csomópontunk, amelyek a twicetwo nevű műveleti csomópont bemeneteire vannak kötve, ami összeszorozza őket. A Python kód a twicetwo.pb protobuf forrásba menti a számítási gráfot, amelyet most a twicetwo.cpp C++ kóddal betöltünk, majd futtatunk:
twicetwo.cpp
// // TensorFlow Hello World 1! // twicetwo.cpp // // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/tensorboard$ python tensorboard.py --logdir=/tmp/twicetwo // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/twicetwo$ bazel build :twicetwo // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/twicetwo$ cp -r ~/Robopsychology/repos/tensorflow/tensorflow/twicetwo/models . // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/twicetwo$ ./twicetwo4 // #include "tensorflow/core/platform/env.h" #include "tensorflow/core/public/session.h" int main(int argc, char **argv) { tensorflow::Session *session; tensorflow::Status status = tensorflow::NewSession(tensorflow::SessionOptions(), &session); if (!status.ok()) { std::cout << "NewSession: " << status.ToString() << std::endl; return -1; } tensorflow::GraphDef graphDef; status = tensorflow::ReadBinaryProto(tensorflow::Env::Default(), "models/twicetwo.pb", &graphDef); if (!status.ok()) { std::cout << "ReadBinaryProto: " << status.ToString() << std::endl; return -2; } // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/twicetwo$ cp -r ~/Robopsychology/repos/tensorflow/tensorflow/twicetwo/models . status = session->Create(graphDef); if (!status.ok()) { std::cout << "Create: " << status.ToString() << std::endl; return -3; } std::vector<tensorflow::Tensor> out; status = session->Run( {}, {"twicetwo"}, {}, &out); if (!status.ok()) { std::cout << "Run: " << status.ToString() << std::endl; return -4; } std::cout << out[0].scalar<int>() << std::endl; // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/twicetwo$ ./twicetwo4 session->Close(); return 0; }
Készítsük el a Bazel BUILD fájl:
cc_binary(
name = "twicetwo",
srcs = ["twicetwo.cpp"],
deps = [
"//tensorflow/core:tensorflow",
]
)
majd a Bazellel készítessük el a futtathatót:
nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/twicetwo$ bazel build :twicetwo
a Python kód kiírta protobuf gráfot másoljuk oda, ahol a futtatható megtalálja:
nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/twicetwo$ cp -r ~/Robopsychology/repos/tensorflow/tensorflow/linreg/models .
majd futtathatjuk a progit:
nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/twicetwo$ ./twicetwo
4
Feladat
Módosítsuk úgy a példát, hogy a C++ programból jöjjön az egyik tagja a szorzásnak!
twicetwo2.py
# # TensorFlow Hello World 1! # Exercise 1 # twicetwo2.py # import tensorflow node1 = tensorflow.Variable(3, name="node1") node2 = tensorflow.constant(2) node_twicetwo = tensorflow.mul(node1, node2, name="twicetwo") sess = tensorflow.Session() sess.run(tensorflow.initialize_all_variables()) print sess.run(node_twicetwo) writer = tensorflow.train.SummaryWriter("/tmp/twicetwo2", sess.graph) tensorflow.train.write_graph(sess.graph_def, "models/", "twicetwo2.pb", as_text=False)
okés:
nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/twicetwo2$ python twicetwo2.py
6
twicetwo2.cpp
Csak a módosítást mutatva
tensorflow::Tensor node1(tensorflow::DT_INT32, tensorflow::TensorShape()); node1.scalar<int>()() = 40; std::vector<std::pair<std::string, tensorflow::Tensor>> inputs = { { "node1", node1 } }; std::vector<tensorflow::Tensor> out; status = session->Run(inputs, {"twicetwo"}, {}, &out); if (!status.ok()) { std::cout << "Run: " << status.ToString() << std::endl; return -4; } std::cout << out[0].scalar<int>() << std::endl;
fordítsuk, futtassuk és vegyük észre, hogy a bemenet valóban a C++ forrásból jött és a visszavett kimenet ezzel az átvett bemenettel készült:
nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/twicetwo2$ ./twicetwo2
80
TensorFlow Hello World 2!
A következő példában a TF bevezető kis példáját módosítjuk: ugyanúgy regressziós egyenest illesztünk a pontokra, de az egyenes meredekségét és eltolását a számítási gráfból kiszedjük a C++ interfészen keresztül.
# # TensorFlow Hello World 2! # linreg.py # # This code is based on the introductory tutorial example of TensorFlow # that can be found at https://www.tensorflow.org/versions/master/get_started/index.html # import tensorflow import numpy b = tensorflow.Variable(numpy.random.randn()) W = tensorflow.Variable(.0) init = tensorflow.initialize_all_variables() sess = tensorflow.Session() sess.run(init) x_data = numpy.random.uniform(-1, 1, 1000) e_data = numpy.random.normal(0, .1, 1000) y_data = x_data * .1 + .3 + e_data y = W * x_data + b loss = tensorflow.reduce_mean(tensorflow.square(y - y_data)) optimizer = tensorflow.train.GradientDescentOptimizer(.5) train = optimizer.minimize(loss) prev = .0 while True: sess.run(train) print(sess.run(W), sess.run(b)) if abs(prev - sess.run(W)) < 0.0001: break prev = sess.run(W) tensorflow.assign(W, tensorflow.constant(W.eval(sess)), name="W") tensorflow.assign(b, tensorflow.constant(b.eval(sess)), name="b") writer = tensorflow.train.SummaryWriter("/tmp/linreg", sess.graph) # nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/tensorboard$ python tensorboard.py --logdir=/tmp/linreg tensorflow.train.write_graph(sess.graph_def, "models/", "linreg.pb", as_text=False) # nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/linreg$ bazel build :linreg # nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/linreg$ cp -r ~/Robopsychology/repos/tensorflow/tensorflow/linreg/models .
nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/linreg$ python linreg.py
(0.023740066, 0.29856035)
(0.048713982, 0.2989215)
(0.065493196, 0.29930139)
(0.076768726, 0.29955661)
(0.084345818, 0.29972813)
(0.089437582, 0.2998434)
(0.092859216, 0.29992086)
(0.095158532, 0.29997289)
(0.096703663, 0.30000788)
(0.097741976, 0.30003136)
(0.098439716, 0.30004716)
(0.098908596, 0.3000578)
(0.099223681, 0.30006492)
(0.099435419, 0.30006972)
(0.099577703, 0.30007294)
(0.099673316, 0.30007508)
A számítási gráf:
// // TensorFlow Hello World 2! // linreg.cpp // // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/linreg$ python linreg.py // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/tensorboard$ python tensorboard.py --logdir=/tmp/linreg // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/linreg$ bazel build :linreg // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/linreg$ cp -r ~/Robopsychology/repos/tensorflow/tensorflow/linreg/models . // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/linreg$ ./linreg // #include "tensorflow/core/platform/env.h" #include "tensorflow/core/public/session.h" int main(int argc, char **argv) { tensorflow::Session *session; tensorflow::Status status = tensorflow::NewSession(tensorflow::SessionOptions(), &session); if (!status.ok()) { std::cout << "NewSession: " << status.ToString() << std::endl; return -1; } tensorflow::GraphDef graphDef; status = tensorflow::ReadBinaryProto(tensorflow::Env::Default(), "models/linreg.pb", &graphDef); if (!status.ok()) { std::cout << "ReadBinaryProto: " << status.ToString() << std::endl; return -2; } // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/linreg$ cp -r ~/Robopsychology/repos/tensorflow/tensorflow/linreg/models . status = session->Create(graphDef); if (!status.ok()) { std::cout << "Create: " << status.ToString() << std::endl; return -3; } std::vector<tensorflow::Tensor> out; status = session->Run( {}, {"W", "b"}, {}, &out); if (!status.ok()) { std::cout << "Run: " << status.ToString() << std::endl; return -4; } std::cout << out[0].scalar<float>() << std::endl; std::cout << out[1].scalar<float>() << std::endl; // nbatfai@robopsy:~/Robopsychology/repos/tensorflow/bazel-bin/tensorflow/linreg$ ./linreg session->Close(); return 0; }
TensorFlow Hello World 3!
Ebben a példában ugyancsak a tutoriál MNIST példáját próbáljuk ki a C++ interfészen keresztül. Első lépésben a Python kódot az előadásban átvesszük, majd úgy módosítjuk, hogy a tanítás után a MNIST adott képét ismertetjük fel, pl. ezt a MNIST jegyet:
amire írja azt ki a módosított Python kód, hogy pl.:
Ez a 42 . indexu tesztkep, ami egy : 4
Ezt a halozat ennek ismeri fel: 4
Majd kézzel rajzolunk egy saját 28x28-as jegyet, mondjuk ezt a 8-ast (a GIMP-el rajzoltam éppen, de fotózhattuk volna is persze)
és ezt is ismerjük fel a MNIST jegyekkel trenírozott hálózattal. C++ tekintetében ugyanezt végigcsináljuk. A számítási gráf C++ progiból inicializálása és a felismerés pontosságának visszaadása még itt történik, a custom kép (a 8 :) felismerése már majd ESAMU esattanként az ESMU cs repóban.
mnist_softmax_UDPROG61.py
# Copyright 2015 The TensorFlow Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================== # Norbert Batfai, 27 Nov 2016 # Some modifications and additions to the original code: # https://github.com/tensorflow/tensorflow/blob/r0.11/tensorflow/examples/tutorials/mnist/mnist_softmax.py # See also http://progpater.blog.hu/2016/11/13/hello_samu_a_tensorflow-bol # ============================================================================== """A very simple MNIST classifier. See extensive documentation at http://tensorflow.org/tutorials/mnist/beginners/index.md """ from __future__ import absolute_import from __future__ import division from __future__ import print_function import argparse # Import data from tensorflow.examples.tutorials.mnist import input_data import tensorflow as tf import matplotlib.pyplot FLAGS = None def readimg(): file = tf.read_file("sajat8a.png") img = tf.image.decode_png(file) return img def main(_): mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True) # Create the model x = tf.placeholder(tf.float32, [None, 784]) W = tf.Variable(tf.zeros([784, 10])) b = tf.Variable(tf.zeros([10])) y = tf.matmul(x, W) + b # Define loss and optimizer y_ = tf.placeholder(tf.float32, [None, 10]) # The raw formulation of cross-entropy, # # tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(tf.nn.softmax(y)), # reduction_indices=[1])) # # can be numerically unstable. # # So here we use tf.nn.softmax_cross_entropy_with_logits on the raw # outputs of 'y', and then average across the batch. cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(y, y_)) train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy) sess = tf.InteractiveSession() # Train tf.initialize_all_variables().run() print("-- A halozat tanitasa") for i in range(1000): batch_xs, batch_ys = mnist.train.next_batch(100) sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys}) if i % 100 == 0: print(i/10, "%") print("----------------------------------------------------------") # Test trained model print("-- A halozat tesztelese") correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) print("-- Pontossag: ", sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})) print("----------------------------------------------------------") print("-- A MNIST 42. tesztkepenek felismerese, mutatom a szamot, a tovabblepeshez csukd be az ablakat") img = mnist.test.images[42] image = img matplotlib.pyplot.imshow(image.reshape(28, 28), cmap=matplotlib.pyplot.cm.binary) matplotlib.pyplot.savefig("4.png") matplotlib.pyplot.show() classification = sess.run(tf.argmax(y, 1), feed_dict={x: [image]}) print("-- Ezt a halozat ennek ismeri fel: ", classification[0]) print("----------------------------------------------------------") print("-- A sajat kezi 8-asom felismerese, mutatom a szamot, a tovabblepeshez csukd be az ablakat") img = readimg() image = img.eval() image = image.reshape(28*28) matplotlib.pyplot.imshow(image.reshape(28, 28), cmap=matplotlib.pyplot.cm.binary) matplotlib.pyplot.savefig("8.png") matplotlib.pyplot.show() classification = sess.run(tf.argmax(y, 1), feed_dict={x: [image]}) print("-- Ezt a halozat ennek ismeri fel: ", classification[0]) print("----------------------------------------------------------") if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument('--data_dir', type=str, default='/tmp/tensorflow/mnist/input_data', help='Directory for storing input data') FLAGS = parser.parse_args() tf.app.run()
Futtassuk:
nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/examples/tutorials/mnist$ python mnist_softmax_UDPROG61.py
Extracting /tmp/tensorflow/mnist/input_data/train-images-idx3-ubyte.gz
Extracting /tmp/tensorflow/mnist/input_data/train-labels-idx1-ubyte.gz
Extracting /tmp/tensorflow/mnist/input_data/t10k-images-idx3-ubyte.gz
Extracting /tmp/tensorflow/mnist/input_data/t10k-labels-idx1-ubyte.gz
-- A halozat tanitasa
0.0 %
10.0 %
20.0 %
30.0 %
40.0 %
50.0 %
60.0 %
70.0 %
80.0 %
90.0 %
----------------------------------------------------------
-- A halozat tesztelese
-- Pontossag: 0.9175
----------------------------------------------------------
-- A MNIST 42. tesztkepenek felismerese, mutatom a szamot, a tovabblepeshez csukd be az ablakat
-- Ezt a halozat ennek ismeri fel: 4
----------------------------------------------------------
-- A sajat kezi 8-asom felismerese, mutatom a szamot, a tovabblepeshez csukd be az ablakat
-- Ezt a halozat ennek ismeri fel: 8
----------------------------------------------------------
nbatfai@robopsy:~/Robopsychology/repos/tensorflow/tensorflow/examples/tutorials/mnist$
Most nézzük meg a TensorBoard segítségével, hogy alakult a tanítás során a hálózat pontossága:
Mit szóltok olyan kis bajnoksághoz, hogy minden tizedes javítás a pontosságon lenne x-sok pont!?
Hivatkozások
- Abadi, M., Agarwal, A., Barham, P., Brevdo, E., Chen, Z., Citro, C., Corrado, G.~S., Davis, A., Dean, J., Devin, M., Ghemawat, S., Goodfellow, I., Harp, A., Irving, G., Isard, M., Jia, Y., Jozefowicz, R., Kaiser, L., Kudlur, M., Levenberg, J., Mane, D., Monga, R., Moore, S., Murray, D., Olah, C., Schuster, M., Shlens, J., Steiner, B., Sutskever, I., Talwar, K., Tucker, P., Vanhoucke, V., Vasudevan, V., Viegas, F., Vinyals, O., Warden, P., Wattenberg, M., Wicke, M., Yu, Y., Zheng, X. (2016) TensorFlow: Large-Scale Machine Learning on Heterogeneous Distributed Systems, ArXiv e-prints, https://arxiv.org/abs/1603.04467
- THE MNIST DATABASE of handwritten digits
http://yann.lecun.com/exdb/mnist/ - MNIST Dataset Loader C++
https://github.com/krck/MNIST_Loader - Loading a TensorFlow graph with the C++ API
https://medium.com/jim-fleming/loading-a-tensorflow-graph-with-the-c-api-4caaff88463f#.cvyx86bgr - JackyTung/tensorgraph
https://github.com/JackyTung/tensorgraph - Jacky Tung Wonderland
http://jackytung8085.blogspot.hu/2016/06/loading-tensorflow-graph-with-c-api-by.html