Generally speaking, we train Tensorflow by writing code in Python, but the data we train needs to be applied in practice. This article will introduce how to train Tensorflow by Python, and the results of training can be applied on Android. Currently, we can also transfer data to the server to identify. Then return the data, but this method is not real-time, need to upload the identification data, and then wait for the return data, in some scenarios, also suitable, you can see the following Java call article.

In actual combat

The actual combat content is based on MNIST experiment to realize the recognition function on the Android platform.

This paper is based on THE MNIST experiment. If you have not done the MNIST experiment, you can first read my previous two articles “Machine learning Tensorflow Notes 1: Hello World to MNIST Experiment” and “Machine learning Tensorflow Notes 2: Ultra-detailed Analysis of MNIST Experiment”.

1. Python saves the training model

In the MNIST experiment, we call the test code immediately after completing the training model. If we want to apply it, it is impossible to train on the mobile terminal. We should put the trained model in the mobile phone or download it to the mobile phone through THE URL, so we need to save our training model.

#! /usr/bin/python # -*- coding: UTF-8 -*- import gzip import sys import struct import numpy from tensorflow.python.framework import graph_util from tensorflow.python.platform import gfile train_images_file = "MNIST_data/train-images-idx3-ubyte.gz" train_labels_file = "MNIST_data/train-labels-idx1-ubyte.gz" t10k_images_file = "MNIST_data/t10k-images-idx3-ubyte.gz" t10k_labels_file = "MNIST_data/t10k-labels-idx1-ubyte.gz" def read32(bytestream): # Since the encoding of network data is the big end, Dt = numpy.dtype(numpy.int32).newByteOrder ('>') data = bytestream.read(4) return numpy.frombuffer(data, dt)[0] def read_labels(filename): with gzip.open(filename) as bytestream: magic = read32(bytestream) numberOfLabels = read32(bytestream) print(magic) print(numberOfLabels) labels = numpy.frombuffer(bytestream.read(numberOfLabels), numpy.uint8) data = numpy.zeros((numberOfLabels, 10)) for i in xrange(len(labels)): data[i][labels[i]] = 1 bytestream.close() return data def read_images(filename): Gzip. Open (filename) as bytestream: magic = read32(bytestream) numberOfImages = read32(bytestream) rows = read32(bytestream) columns = read32(bytestream) images = numpy.frombuffer(bytestream.read(numberOfImages * rows * columns), numpy.uint8) images.shape = (numberOfImages, rows * columns) images = images.astype(numpy.float32) images = numpy.multiply(images, Bytestream.close () print(magic) print(numberOfImages) Print (rows) print(columns) return images # Train_labels contains 60000 number labels. Returns an array train_labels = read_labels(train_labels_file) # print(labels) train_images = read_images(train_images_file) test_labels = read_labels(t10k_labels_file) # print(labels) test_images = read_images(t10k_images_file) import tensorflow as tf x = tf.placeholder("float", [None, 784.],name='input/x_input') W = tf.Variable(tf.zeros([784., 10.])) b = tf.Variable(tf.zeros([10.])) y = tf.nn.softmax(tf.matmul(x, W) + b) y_ = tf.placeholder("float",name='input/y_input') cross_entropy = -tf.reduce_sum(y_ * tf.log(y)) train_step = Tf. Train. GradientDescentOptimizer (0.01). Minimize (cross_entropy) init = tf. Initialize_all_variables (sess) = tf. The Session ()  sess.run(init) for i in range(1200): batch_xs = train_images[50 * i:50 * i + 50] batch_ys = train_labels[50 * i:50 * i + 50] sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys}) correct_prediction = tf.equal(tf.argmax(y, 1, output_type='int32', name='output'), tf.argmax(y_, 1, output_type='int32')) # correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) print sess.run(accuracy, feed_dict={x: test_images, y_: Test_labels}) # Save trained models # The parameter output_node_names is used to specify the node name for output. Output_node_names =['output'] corresponds to pre_num=tf.argmax(y,1,name="output"), output_graph_def = graph_util.convert_variables_to_constants(sess, sess.graph_def, output_node_names=['output']) with tf.gfile.FastGFile('model/mnist.pb', mode='wb') as f: In # 'wb' w stands for write file, b stands for write data to file in binary mode. f.write(output_graph_def.SerializeToString()) sess.close()Copy the code

By simply modifying the code, it is easy to save the training model locally.

Tests whether the exported model is available
#! /usr/bin/python # -*- coding: Utf-8 -* -import tensorflow as tf import numpy as NP from PIL import Image # model path model_path = 'model/mnist testImage = Image.open("data/test_image.png") with tf.Graph().as_default(): output_graph_def = tf.GraphDef() with open(model_path, "rb") as f: output_graph_def.ParseFromString(f.read()) tf.import_graph_def(output_graph_def, name="") with tf.Session() as sess: tf.global_variables_initializer().run() # x_test = x_test.reshape(1, 28 * 28) input_x = sess.graph.get_tensor_by_name("input/x_input:0") output = sess.graph.get_tensor_by_name("output:0") TestImage = testimage. convert('L') testImage= testimage. resize((28, 28)) test_input=np.array(testImage) test_input = test_input.reshape(1, 28 * 28) pre_num = sess.run(output, Feed_dict ={input_x: test_input})# print(' test_input ',pre_num)Copy the code

2. Configure the project

  1. In the app directorybuild.gradleAdd Gradle dependencies. Since the so file is very large, it is recommended to support only ARM. After introducing Tensorflow, APK is only increased4.9 MBIf artificial intelligence is regarded as an important business, this cost is worth it, and I will write it laterTensorflow LiteIs smaller and more suitable for mobile devices.
android { //... buildTypes { debug { minifyEnabled false debuggable = false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' ndk { abiFilters "armeabi-v7a","x86" } } release { minifyEnabled false debuggable = false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' ndk { abiFilters "armeabi-v7a" } } } } dependencies { implementation 'org. Tensorflow: tensorflow - android: 1.8.0 comes with'}Copy the code
  1. Put the training model saved above into the Android projectassetsPut the images you want to test into the folderdrawableUnder the folder.
├ ─ ─ the main │ ├ ─ ─ AndroidManifest. XML │ ├ ─ ─ assets │ │ └ ─ ─ mnist. Pb │ └ ─ ─ res │ ├ ─ ─ drawable │ │ └ ─ ─ test_image. PNGCopy the code


test_image.png

image.png




image.png

The test model
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val bitmap = BitmapFactory.decodeResource(resources, R.drawable.test_image) val tfi = TensorFlowInferenceInterface(assets, "mnist.pb") val inputData = bitmapToFloatArray(bitmap, 28f, 28f) tfi.feed("input/x_input", inputData, 1, 784) val outputs = IntArray(1) input = IntArray(1) Elsif (outputs [0], outputs) imageView.setimageBitMap (bitmap) textView.text =" "+ outputs[0]} /** * convert the bitmap to (line-first) a float array, with each pixel normalized to between 0 and 1. @param rx scales the image to the specified size (column) ->28 * @param RY scales the image to the specified size (row) ->28 * @return Returns the normalized one-dimensional float array ->28*28 */ private fun bitmapToFloatArray(bitmap: Bitmap, rx: Float, ry: Float): FloatArray {var height = bitmap.height var width = bitmap.width // Calculates the scaling ratio  ry / height val matrix = Matrix() matrix.postScale(scaleWidth, scaleHeight) val bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true) height = bitmap.height width = bitmap.width val result = FloatArray(height * width) var k = 0 for (row in 0 until height) { for (col in 0 until width) { val argb = bitmap.getPixel(col, Row) val r = color.red (arGB) val g = color.green (arGB) val b = color.blue (arGB) Assert (r == g && g == b) result[k++] = r / 255.0f}} return result}}Copy the code

Layout file

<? The XML version = "1.0" encoding = "utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:padding="10dp" android:orientation="vertical"> <ImageView android:id="@+id/imageView" android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center" android:scaleType="fitXY" /> <TextView android:id="@+id/textView" android:layout_width="match_parent" Android :layout_height="wrap_content" Android :layout_marginTop="20dp" Android :gravity="center" Android :text=" " /> </LinearLayout>Copy the code
The results of


image.png

The source code

Github.com/taoweiji/Te…