Last active
June 16, 2018 09:28
-
-
Save bulentsiyah/02d03f3dfecd71eea42c9f5b257d1bf7 to your computer and use it in GitHub Desktop.
ANDROİD’DE MNIST VERİ SETİYLE ÖNCEDEN EĞİTİLMİŞ TENSORFLOW MODELİNİ KULLANMA | TENSORFLOW | ANDROİD -- http://www.bulentsiyah.com/androidde-mnist-veri-setiyle-onceden-egitilmis-tensorflow-modelini-kullanma-tensorflow-android/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import tensorflow as tf | |
from tensorflow.examples.tutorials.mnist import input_data | |
mnist_data = input_data.read_data_sets('MNIST_data', one_hot=True) | |
# Function to create a weight neuron using a random number. Training will assign a real weight later | |
def weight_variable(shape, name): | |
initial = tf.truncated_normal(shape, stddev=0.1) | |
return tf.Variable(initial, name=name) | |
# Function to create a bias neuron. Bias of 0.1 will help to prevent any 1 neuron from being chosen too often | |
def biases_variable(shape, name): | |
initial = tf.constant(0.1, shape=shape) | |
return tf.Variable(initial, name=name) | |
# Function to create a convolutional neuron. Convolutes input from 4d to 2d. This helps streamline inputs | |
def conv_2d(x, W, name): | |
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME', name=name) | |
# Function to create a neuron to represent the max input. Helps to make the best prediction for what comes next | |
def max_pool(x, name): | |
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME', name=name) | |
# A way to input images (as 784 element arrays of pixel values 0 - 1) | |
x_input = tf.placeholder(dtype=tf.float32, shape=[None, 784], name='x_input') | |
# A way to input labels to show model what the correct answer is during training | |
y_input = tf.placeholder(dtype=tf.float32, shape=[None, 10], name='y_input') | |
# First convolutional layer - reshape/resize images | |
# A weight variable that examines batches of 5x5 pixels, returns 32 features (1 feature per bit value in 32 bit float) | |
W_conv1 = weight_variable([5, 5, 1, 32], 'W_conv1') | |
# Bias variable to add to each of the 32 features | |
b_conv1 = biases_variable([32], 'b_conv1') | |
# Reshape each input image into a 28 x 28 x 1 pixel matrix | |
x_image = tf.reshape(x_input, [-1, 28, 28, 1], name='x_image') | |
# Flattens filter (W_conv1) to [5 * 5 * 1, 32], multiplies by [None, 28, 28, 1] to associate each 5x5 batch with the | |
# 32 features, and adds biases | |
h_conv1 = tf.nn.relu(conv_2d(x_image, W_conv1, name='conv1') + b_conv1, name='h_conv1') | |
# Takes windows of size 2x2 and computes a reduction on the output of h_conv1 (computes max, used for better prediction) | |
# Images are reduced to size 14 x 14 for analysis | |
h_pool1 = max_pool(h_conv1, name='h_pool1') | |
# Second convolutional layer, reshape/resize images | |
# Does mostly the same as above but converts each 32 unit output tensor from layer 1 to a 64 feature tensor | |
W_conv2 = weight_variable([5, 5, 32, 64], 'W_conv2') | |
b_conv2 = biases_variable([64], 'b_conv2') | |
h_conv2 = tf.nn.relu(conv_2d(h_pool1, W_conv2, name='conv2') + b_conv2, name='h_conv2') | |
# Images at this point are reduced to size 7 x 7 for analysis | |
h_pool2 = max_pool(h_conv2, name='h_pool2') | |
# First dense layer, performing calculation based on previous layer output | |
# Each image is 7 x 7 at the end of the previous section and outputs 64 features, we want 32 x 32 neurons = 1024 | |
W_dense1 = weight_variable([7 * 7 * 64, 1024], name='W_dense1') | |
# bias variable added to each output feature | |
b_dense1 = biases_variable([1024], name='b_dense1') | |
# Flatten each of the images into size [None, 7 x 7 x 64] | |
h_pool_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64], name='h_pool_flat') | |
# Multiply weights by the outputs of the flatten neuron and add biases | |
h_dense1 = tf.nn.relu(tf.matmul(h_pool_flat, W_dense1, name='matmul_dense1') + b_dense1, name='h_dense1') | |
# Dropout layer prevents overfitting or recognizing patterns where none exist | |
# Depending on what value we enter into keep_prob, it will apply or not apply dropout layer | |
keep_prob = tf.placeholder(dtype=tf.float32, name='keep_prob') | |
# Dropout layer will be applied during training but not testing or predicting | |
h_drop1 = tf.nn.dropout(h_dense1, keep_prob, name='h_drop1') | |
# Readout layer used to format output | |
# Weight variable takes inputs from each of the 1024 neurons from before and outputs an array of 10 elements | |
W_readout1 = weight_variable([1024, 10], name='W_readout1') | |
# Apply bias to each of the 10 outputs | |
b_readout1 = biases_variable([10], name='b_readout1') | |
# Perform final calculation by multiplying each of the neurons from dropout layer by weights and adding biases | |
y_readout1 = tf.add(tf.matmul(h_drop1, W_readout1, name='matmul_readout1'), b_readout1, name='y_readout1') | |
# Softmax cross entropy loss function compares expected answers (labels) vs actual answers (logits) | |
cross_entropy_loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_input, logits=y_readout1)) | |
# Adam optimizer aims to minimize loss | |
train_step = tf.train.AdamOptimizer(0.0001).minimize(cross_entropy_loss) | |
# Compare actual vs expected outputs to see if highest number is at the same index, true if they match and false if not | |
correct_prediction = tf.equal(tf.argmax(y_input, 1), tf.argmax(y_readout1, 1)) | |
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) | |
# Used to save the graph and weights | |
saver = tf.train.Saver() | |
# Run in with statement so session only exists within it | |
with tf.Session() as sess: | |
sess.run(tf.global_variables_initializer()) | |
# Save the graph shape and node names to pbtxt file | |
tf.train.write_graph(sess.graph_def, '.', 'advanced_mnist.pbtxt', False) | |
# Train the model, running through data 20000 times in batches of 50 | |
# Print out step # and accuracy every 100 steps and final accuracy at the end of training | |
# Train by running train_step and apply dropout by setting keep_prob to 0.5 | |
for i in range(20000): | |
batch = mnist_data.train.next_batch(50) | |
if i % 100 == 0: | |
train_accuracy = accuracy.eval(feed_dict={x_input: batch[0], y_input: batch[1], keep_prob: 1.0}) | |
print("step %d, training accuracy %g" %(i, train_accuracy)) | |
train_step.run(feed_dict={x_input: batch[0], y_input: batch[1], keep_prob: 0.5}) | |
print("test accuracy %g" % accuracy.eval(feed_dict={x_input: mnist_data.test.images, | |
y_input: mnist_data.test.labels, keep_prob: 1.0})) | |
# Save the session with graph shape and node weights | |
saver.save(sess, 'advanced_mnist.ckpt') | |
# Make a prediction | |
print(sess.run(y_readout1, feed_dict={x_input: [mnist_data.test.images[0]], keep_prob: 1.0})) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
apply plugin: 'com.android.application' | |
android { | |
compileSdkVersion 27 | |
defaultConfig { | |
applicationId "bulentsiyah.com.mlkit" | |
minSdkVersion 22 | |
targetSdkVersion 27 | |
versionCode 1 | |
versionName "1.0" | |
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" | |
} | |
buildTypes { | |
release { | |
minifyEnabled false | |
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' | |
} | |
} | |
sourceSets { | |
main { | |
jniLibs.srcDirs = ['libs'] | |
} | |
} | |
} | |
dependencies { | |
implementation fileTree(dir: 'libs', include: ['*.jar']) | |
implementation 'com.android.support:appcompat-v7:27.1.1' | |
implementation 'com.android.support.constraint:constraint-layout:1.1.0' | |
testImplementation 'junit:junit:4.12' | |
androidTestImplementation 'com.android.support.test:runner:1.0.2' | |
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import tensorflow as tf | |
from tensorflow.python.tools import freeze_graph, optimize_for_inference_lib | |
# Saving the graph as a pb file taking data from pbtxt and ckpt files and providing a few operations | |
freeze_graph.freeze_graph('advanced_mnist.pbtxt', | |
'', | |
True, | |
'advanced_mnist.ckpt', | |
'y_readout1', | |
'save/restore_all', | |
'save/Const:0', | |
'frozen_advanced_mnist.pb', | |
True, | |
'') | |
# Read the data form the frozen graph pb file | |
input_graph_def = tf.GraphDef() | |
with tf.gfile.Open('frozen_advanced_mnist.pb', 'rb') as f: | |
data = f.read() | |
input_graph_def.ParseFromString(data) | |
# Optimize the graph with input and output nodes | |
output_graph_def = optimize_for_inference_lib.optimize_for_inference( | |
input_graph_def, | |
['x_input', 'keep_prob'], | |
['y_readout1'], | |
tf.float32.as_datatype_enum) | |
# Save the optimized graph to the optimized pb file | |
f = tf.gfile.FastGFile('optimized_advanced_mnist.pb', 'w') | |
f.write(output_graph_def.SerializeToString()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="utf-8"?> | |
<android.support.constraint.ConstraintLayout | |
xmlns:android="http://schemas.android.com/apk/res/android" | |
xmlns:app="http://schemas.android.com/apk/res-auto" | |
xmlns:tools="http://schemas.android.com/tools" | |
android:layout_width="match_parent" | |
android:layout_height="match_parent"> | |
<ImageView | |
android:id="@+id/image_view" | |
android:layout_width="300dp" | |
android:layout_height="300dp" | |
app:layout_constraintBottom_toTopOf="@+id/predict_button" | |
app:layout_constraintLeft_toLeftOf="parent" | |
app:layout_constraintRight_toRightOf="parent" | |
app:layout_constraintTop_toTopOf="parent" | |
android:contentDescription="@string/image_view_content_description"/> | |
<Button | |
android:id="@+id/predict_button" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
app:layout_constraintBottom_toTopOf="@+id/next_image_button" | |
app:layout_constraintLeft_toLeftOf="parent" | |
app:layout_constraintRight_toRightOf="parent" | |
app:layout_constraintTop_toBottomOf="@+id/image_view" | |
android:text="@string/predict_button_text" | |
android:onClick="predictDigitClick"/> | |
<Button | |
android:id="@+id/next_image_button" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
app:layout_constraintBottom_toTopOf="@+id/text_view" | |
app:layout_constraintLeft_toLeftOf="parent" | |
app:layout_constraintRight_toRightOf="parent" | |
app:layout_constraintTop_toBottomOf="@+id/predict_button" | |
android:text="@string/next_image_button_text" | |
android:onClick="loadNextImageClick"/> | |
<TextView | |
android:id="@+id/text_view" | |
android:layout_width="wrap_content" | |
android:layout_height="wrap_content" | |
app:layout_constraintBottom_toBottomOf="parent" | |
app:layout_constraintLeft_toLeftOf="parent" | |
app:layout_constraintRight_toRightOf="parent" | |
app:layout_constraintTop_toBottomOf="@+id/next_image_button" | |
android:text="@string/text_view_text" | |
android:textSize="20sp"/> | |
</android.support.constraint.ConstraintLayout> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package bulentsiyah.com.mlkit; | |
import android.graphics.Bitmap; | |
import android.graphics.BitmapFactory; | |
import android.support.v7.app.AppCompatActivity; | |
import android.os.Bundle; | |
import android.view.View; | |
import android.widget.ImageView; | |
import android.widget.TextView; | |
import org.tensorflow.contrib.android.TensorFlowInferenceInterface; | |
public class MNISTOrnegi extends AppCompatActivity { | |
ImageView imageView; | |
TextView textView; | |
Boolean SimpleTrue_AdvancedFalse = false; | |
static { | |
System.loadLibrary("tensorflow_inference"); | |
} | |
private static final String MODEL_FILE_Simple = "file:///android_asset/optimized_frozen_mnist_model.pb"; | |
private static final String INPUT_NODE = "x_input"; | |
private static final int[] INPUT_SHAPE = {1, 784}; | |
private static final String OUTPUT_NODE_Simple = "y_actual"; | |
private static final String MODEL_FILE = "file:///android_asset/optimized_advanced_mnist.pb"; | |
private static final int[] INPUT_SIZE = {1, 784}; | |
private static final String KEEP_PROB = "keep_prob"; | |
private static final int[] KEEP_PROB_SIZE = {1}; | |
private static final String OUTPUT_NODE = "y_readout1"; | |
private TensorFlowInferenceInterface inferenceInterface; | |
private int imageListIndex = 9; | |
private final int[] imageIDList = { | |
R.drawable.digit0, | |
R.drawable.digit1, | |
R.drawable.digit2, | |
R.drawable.digit3, | |
R.drawable.digit4, | |
R.drawable.digit5, | |
R.drawable.digit6, | |
R.drawable.digit7, | |
R.drawable.digit8, | |
R.drawable.digit9 | |
}; | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_mnistornegi); | |
imageView = (ImageView) findViewById(R.id.image_view); | |
textView = (TextView) findViewById(R.id.text_view); | |
inferenceInterface = new TensorFlowInferenceInterface(); | |
if(SimpleTrue_AdvancedFalse) { | |
inferenceInterface.initializeTensorFlow(getAssets(), MODEL_FILE_Simple); | |
}else{ | |
inferenceInterface.initializeTensorFlow(getAssets(), MODEL_FILE); | |
} | |
} | |
public void predictDigitClick(View view) { | |
float[] pixelBuffer = convertImage(); | |
float[] results = formPrediction(pixelBuffer); | |
printResults(results); | |
} | |
private void printResults(float[] results) { | |
float max = 0; | |
float secondMax = 0; | |
int maxIndex = 0; | |
int secondMaxIndex = 0; | |
for(int i = 0; i < 10; i++) { | |
if (results[i] > max) { | |
secondMax = max; | |
secondMaxIndex = maxIndex; | |
max = results[i]; | |
maxIndex = i; | |
} else if (results[i] < max && results[i] > secondMax) { | |
secondMax = results[i]; | |
secondMaxIndex = i; | |
} | |
} | |
String output = "Model ilk tahmin: " + String.valueOf(maxIndex) + | |
", ikinci tahmin: " + String.valueOf(secondMaxIndex); | |
textView.setText(output); | |
} | |
private float[] formPrediction(float[] pixelBuffer) { | |
if(SimpleTrue_AdvancedFalse) { | |
inferenceInterface.fillNodeFloat(INPUT_NODE, INPUT_SHAPE, pixelBuffer); | |
inferenceInterface.runInference(new String[]{OUTPUT_NODE_Simple}); | |
float[] results = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; | |
inferenceInterface.readNodeFloat(OUTPUT_NODE_Simple, results); | |
return results; | |
}else{ | |
inferenceInterface.fillNodeFloat(INPUT_NODE, INPUT_SIZE, pixelBuffer); | |
inferenceInterface.fillNodeFloat(KEEP_PROB, KEEP_PROB_SIZE, new float[] {0.5f}); | |
inferenceInterface.runInference(new String[] {OUTPUT_NODE}); | |
float[] outputs = new float[10]; | |
inferenceInterface.readNodeFloat(OUTPUT_NODE, outputs); | |
return outputs; | |
} | |
} | |
private float[] convertImage() { | |
Bitmap imageBitmap = BitmapFactory.decodeResource(getResources(), | |
imageIDList[imageListIndex]); | |
//ölçekle | |
imageBitmap = Bitmap.createScaledBitmap(imageBitmap, 28, 28, true); | |
imageView.setImageBitmap(imageBitmap); | |
int[] imageAsIntArray = new int[784]; | |
float[] imageAsFloatArray = new float[784]; | |
//getPixel metodu aldığı piksel kordinat parametrelerindeki pixel bilgilerine ilişkin int bir değer döndürür. | |
// Bu değer android.graphics.Color sınıfına ilişkin int türden değerdir. | |
// Pixel değerlerine ilişkin Alpha, Red, Green, Blue değerleri sırasıyla | |
// Alpha, Red, Green, Blue static metotları ile elde edilebilir. | |
imageBitmap.getPixels(imageAsIntArray, 0, 28, 0, 0, 28, 28); | |
for (int i = 0; i < 784; i++) { | |
imageAsFloatArray[i] = imageAsIntArray[i] / -16777216; //256x256x256= 16,777,216 | |
} | |
return imageAsFloatArray; | |
} | |
public void loadNextImageClick(View view) { | |
if (imageListIndex >= 9) { | |
imageListIndex = 0; | |
} else { | |
imageListIndex += 1; | |
} | |
imageView.setImageDrawable(getDrawable(imageIDList[imageListIndex])); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Freeze_Graph.py | |
import tensorflow as tf | |
from tensorflow.python.tools import freeze_graph, optimize_for_inference_lib | |
freeze_graph.freeze_graph(input_graph='mnist_model_n.pbtxt', | |
input_saver='', | |
input_binary=True, | |
input_checkpoint='mnist_model_n.ckpt', | |
output_node_names='y_actual', | |
restore_op_name='save/restore_all', | |
filename_tensor_name='save/Const:0', | |
output_graph='frozen_mnist_model.pb', | |
clear_devices=True, | |
initializer_nodes='') | |
input_graph_def = tf.GraphDef() | |
with tf.gfile.Open('frozen_mnist_model.pb', 'rb') as f: | |
data = f.read() | |
input_graph_def.ParseFromString(data) | |
output_graph_def = optimize_for_inference_lib.optimize_for_inference(input_graph_def=input_graph_def, | |
input_node_names=['x_input'], | |
output_node_names=['y_actual'], | |
placeholder_type_enum=tf.float32.as_datatype_enum) | |
f = tf.gfile.FastGFile(name='optimized_frozen_mnist_model.pb', | |
mode='w') | |
f.write(file_content=output_graph_def.SerializeToString()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MNIST_Model.py | |
import tensorflow as tf | |
from tensorflow.examples.tutorials.mnist import input_data | |
# Contains all of the images and labels (train and test) in the MNIST_data data set | |
mnist_data = input_data.read_data_sets('MNIST_data', one_hot=True) | |
#train_image = mnist_data.train.images[0] | |
#train_label = mnist_data.train.labels[0] | |
#print(train_image) | |
#print(train_label) | |
# y = Wx + b | |
# Input to the graph, takes in any number of images (784 element pixel arrays) | |
x_input = tf.placeholder(dtype=tf.float32, shape=[None, 784], name='x_input') | |
# Weights to be multiplied by input | |
W = tf.Variable(initial_value=tf.zeros(shape=[784, 10]), name='W') | |
# Biases to be added to weights * inputs | |
b = tf.Variable(initial_value=tf.zeros(shape=[10]), name='b') | |
# Actual model prediction based on input and current values of W and b | |
y_actual = tf.add(x=tf.matmul(a=x_input, b=W, name='matmul'), y=b, name='y_actual') | |
# Input to enter correct answer for comparison during training | |
y_expected = tf.placeholder(dtype=tf.float32, shape=[None, 10], name='y_expected') | |
# Cross entropy loss function because output is a list of possibilities (% certainty of the correct answer) | |
cross_entropy_loss = tf.reduce_mean( | |
input_tensor=tf.nn.softmax_cross_entropy_with_logits(labels=y_expected, logits=y_actual), | |
name='cross_entropy_loss') | |
# Classic gradient descent optimizer aims to minimize the difference between expected and actual values (loss) | |
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.5, name='optimizer') | |
train_step = optimizer.minimize(loss=cross_entropy_loss, name='train_step') | |
saver = tf.train.Saver() | |
# Create the session to run the nodes | |
session = tf.InteractiveSession() | |
session.run(tf.global_variables_initializer()) | |
tf.train.write_graph(graph_or_graph_def=session.graph_def, | |
logdir='.', | |
name='mnist_model_n.pbtxt', | |
as_text=False) | |
# Train the model by fetching batches of 100 images and labels at a time and running train_step | |
# Run through the batches 1000 times (epochs) | |
for _ in range(1000): | |
batch = mnist_data.train.next_batch(100) | |
train_step.run(feed_dict={x_input: batch[0], y_expected: batch[1]}) | |
saver.save(sess=session,save_path='./mnist_model_n.ckpt') | |
# Measure accuracy by comparing the predicted values to the correct values and calculating how many of them match | |
correct_prediction = tf.equal(x=tf.argmax(y_actual, 1), y=tf.argmax(y_expected, 1)) | |
accuracy = tf.reduce_mean(tf.cast(x=correct_prediction, dtype=tf.float32)) | |
print(accuracy.eval(feed_dict={x_input: mnist_data.test.images, y_expected: mnist_data.test.labels})) | |
# Test a prediction on a single image | |
print(session.run(fetches=y_actual, feed_dict={x_input: [mnist_data.test.images[0]]})) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment