In [1]:
%matplotlib inline
import os
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

In [2]:
local_dir = os.path.join("/DATA",os.environ.get("USER"),"MNIST_data")
os.makedirs(local_dir,mode=0o755, exist_ok=True)

In [ ]:


In [3]:
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets(local_dir, one_hot=True)


Extracting /DATA/marcin.kostur/MNIST_data/train-images-idx3-ubyte.gz
Extracting /DATA/marcin.kostur/MNIST_data/train-labels-idx1-ubyte.gz
Extracting /DATA/marcin.kostur/MNIST_data/t10k-images-idx3-ubyte.gz
Extracting /DATA/marcin.kostur/MNIST_data/t10k-labels-idx1-ubyte.gz

Konstrukcja sieci konwolucyjnej

  • dane przedstawiamy jako tablicę 28x28
  • bierzemy 32 różne wagi-kernele o rozmiarze 5x5 i wykonujemy każdą z nich konwoluję obrazka 28x28 -> 28x28
  • działamy na kazdy pixel z osobna funkcją nieliniową Relu
  • po konwolucji w każdym obrazku z każdej grupy 2x2 pixeli zostawimy ten najjaśniejszy max_pool_2x2(x) - obrazek jest juz 14x14
  • bierzemy 64 różne wagi-kernele o rozmiarze 5x5 i wykonujemy każdym z nich konwoluję 32 obrazków 14x14 -> 14x14
  • działamy na kazdy pixel z osobna funkcją nieliniową Relu
  • po konwolucji w każdym obrazku z każdej grupy 2x2 pixeli zostawimy ten najjaśniejszy max_pool_2x2(x) - obrazek jest juz 7x7
  • zamieniamy 64x otrzymane obrazki 7x7 na wektor
  • wektor ten dajemy na wejscię 1024 percetronowej warstwy "fully connected"
  • stosujemy dropout
  • ostatnią warstwą jest 10 perceptronów z funkcją softmax

In [4]:
def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)

def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

In [5]:
def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                        strides=[1, 2, 2, 1], padding='SAME')

In [6]:
x = tf.placeholder(tf.float32, shape=[None, 784])
y_ = tf.placeholder(tf.float32, shape=[None, 10])

In [ ]:


In [7]:
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])

In [8]:
x_image = tf.reshape(x, [-1,28,28,1])

In [9]:
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

In [10]:
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

In [11]:
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

In [12]:
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

In [13]:
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2

In [14]:
cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

In [15]:
config = tf.ConfigProto()
#config.gpu_options.allow_growth = True
config.gpu_options.per_process_gpu_memory_fraction = 0.50

sess = tf.InteractiveSession(config=config)
tf.global_variables_initializer().run()

Test run

Pouczające jest prześledzenie jak zmienia się w trakcie przejścia przez sieć jeden obrazek:


In [16]:
batch = mnist.train.next_batch(1)
print( batch[0].shape )


(1, 784)

In [17]:
sess.run(x_image,feed_dict={ x:batch[0], y_: batch[1], keep_prob: 1.0}).shape


Out[17]:
(1, 28, 28, 1)

In [18]:
sess.run(h_conv1,feed_dict={ x:batch[0], y_: batch[1], keep_prob: 1.0}).shape


Out[18]:
(1, 28, 28, 32)

In [19]:
sess.run(h_pool1,feed_dict={ x:batch[0], y_: batch[1], keep_prob: 1.0}).shape


Out[19]:
(1, 14, 14, 32)

In [20]:
sess.run(h_conv2,feed_dict={ x:batch[0], y_: batch[1], keep_prob: 1.0}).shape


Out[20]:
(1, 14, 14, 64)

In [21]:
sess.run(h_pool2,feed_dict={ x:batch[0], y_: batch[1], keep_prob: 1.0}).shape


Out[21]:
(1, 7, 7, 64)

In [22]:
sess.run(h_pool2_flat,feed_dict={ x:batch[0], y_: batch[1], keep_prob: 1.0}).shape


Out[22]:
(1, 3136)

In [23]:
sess.run(h_fc1_drop,feed_dict={ x:batch[0], y_: batch[1], keep_prob: 1.0}).shape


Out[23]:
(1, 1024)

In [24]:
sess.run(y_conv,feed_dict={ x:batch[0], y_: batch[1], keep_prob: 1.0}).shape


Out[24]:
(1, 10)

In [ ]:


In [25]:
%%time 
sess.run(tf.global_variables_initializer())
for i in range(1000):
    batch = mnist.train.next_batch(150)
    if i%100 == 0:
        train_accuracy = accuracy.eval(feed_dict={ x:batch[0], y_: batch[1], keep_prob: 0.8})
        print("step %d, training accuracy %g"%(i, train_accuracy))
    
    train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

print("test accuracy %g"%accuracy.eval(feed_dict={
    x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))


step 0, training accuracy 0.0666667
step 100, training accuracy 0.806667
step 200, training accuracy 0.933333
step 300, training accuracy 0.933333
step 400, training accuracy 0.933333
step 500, training accuracy 0.973333
step 600, training accuracy 0.953333
step 700, training accuracy 0.953333
step 800, training accuracy 0.966667
step 900, training accuracy 0.973333
test accuracy 0.9718
CPU times: user 19.3 s, sys: 3.04 s, total: 22.3 s
Wall time: 22 s

Analiza wyników

Możemy obejrzeć jakie błędy popełnia sieć.


In [26]:
P = sess.run(correct_prediction,feed_dict={ x:mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0})
P.shape


Out[26]:
(10000,)

In [27]:
Bad_x = mnist.test.images[np.where(P==False)[0],:]
Bad_x_truelabels = mnist.test.labels[np.where(P==False)[0],:]
Bad_x.shape


Out[27]:
(282, 784)

In [28]:
prediction =sess.run( tf.argmax(y_conv,1),
                          feed_dict={ x:Bad_x, y_: Bad_x_truelabels, keep_prob: 1.0})

In [29]:
prediction


Out[29]:
array([4, 3, 8, 2, 0, 4, 3, 1, 7, 3, 4, 0, 8, 5, 3, 0, 3, 3, 9, 2, 3, 8, 1,
       3, 4, 9, 6, 8, 9, 2, 3, 3, 7, 6, 0, 5, 9, 8, 6, 9, 1, 5, 2, 4, 9, 5,
       1, 2, 7, 0, 2, 3, 1, 9, 6, 7, 2, 3, 3, 9, 6, 7, 7, 3, 0, 9, 2, 7, 4,
       5, 3, 4, 3, 3, 4, 3, 2, 0, 2, 9, 3, 8, 7, 9, 0, 7, 0, 2, 9, 1, 9, 2,
       5, 1, 6, 0, 0, 7, 2, 1, 1, 4, 4, 1, 5, 4, 5, 7, 2, 8, 0, 1, 3, 3, 0,
       4, 0, 0, 5, 5, 5, 8, 1, 5, 7, 2, 5, 9, 0, 3, 3, 9, 2, 3, 9, 0, 7, 1,
       4, 9, 0, 5, 3, 3, 4, 5, 3, 3, 9, 2, 2, 2, 8, 8, 4, 5, 4, 6, 3, 3, 3,
       6, 4, 9, 5, 2, 3, 0, 3, 4, 0, 7, 1, 7, 3, 1, 3, 3, 7, 7, 3, 4, 5, 3,
       1, 8, 3, 7, 1, 5, 3, 2, 2, 4, 4, 9, 3, 2, 5, 8, 0, 5, 0, 6, 2, 0, 8,
       1, 4, 3, 3, 2, 9, 2, 6, 3, 8, 7, 6, 9, 7, 0, 0, 8, 0, 3, 3, 0, 0, 3,
       5, 0, 6, 0, 7, 3, 7, 1, 7, 6, 5, 5, 0, 4, 2, 8, 1, 1, 5, 5, 6, 6, 5,
       3, 9, 2, 2, 2, 2, 2, 5, 5, 7, 0, 0, 6, 6, 0, 0, 0, 0, 1, 8, 7, 5, 8,
       8, 0, 5, 8, 7, 6])

In [30]:
Bad_x_true = np.argmax(Bad_x_truelabels,axis=1)

In [31]:
Bad_x.shape


Out[31]:
(282, 784)

In [32]:
Bad_x_true.shape


Out[32]:
(282,)

In [33]:
prediction.shape


Out[33]:
(282,)

In [ ]:


In [ ]:


In [34]:
#Imports for visualization
import PIL.Image
from io import BytesIO
from IPython.display import clear_output, Image, display
def DisplayArray(a, fmt='jpeg', rng=[0,1]):
    """Display an array as a picture."""
    a = (a - rng[0])/float(rng[1] - rng[0])*255
    a = np.uint8(np.clip(a, 0, 255))
    f = BytesIO()
    PIL.Image.fromarray(a).save(f, fmt)
    display(Image(data=f.getvalue()))

In [35]:
from time import sleep

In [ ]:


In [36]:
for ith in range(Bad_x_true.shape[0]//20):
    print("zamiast ",Bad_x_true[ith], "sieć odczytała",prediction[ith],end="")
    DisplayArray( Bad_x[ith].reshape((28,28)) ) 
    #sleep(0.5)
    #clear_output(wait=True)


zamiast  9 sieć odczytała 4
zamiast  2 sieć odczytała 3
zamiast  9 sieć odczytała 8
zamiast  4 sieć odczytała 2
zamiast  6 sieć odczytała 0
zamiast  8 sieć odczytała 4
zamiast  2 sieć odczytała 3
zamiast  9 sieć odczytała 1
zamiast  2 sieć odczytała 7
zamiast  5 sieć odczytała 3
zamiast  6 sieć odczytała 4
zamiast  6 sieć odczytała 0
zamiast  9 sieć odczytała 8
zamiast  3 sieć odczytała 5

In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]:


In [ ]: