Training a model for the Tribune

This notebook uses the Tensorflow for poets tutorial to train a new model for classifying images in the Tribune collection.

First we'll clone the code repository.

In [ ]:
!git clone https://github.com/googlecodelabs/tensorflow-for-poets-2

Now let's move into the new directory

In [6]:
cd tensorflow-for-poets-2
[Errno 2] No such file or directory: 'tensorflow-for-poets-2'
/Users/tim/mycode/glam-workbench/image-recognition/notebooks/tensorflow-for-poets-2

Our categories

For our initial experiment we're going to try and distinguish between two categories — protests and portraits.

In [7]:
img_sets = {
    'protests': ['FL4520808', 'FL4520807', 'FL4520809', 'FL4520810', 'FL4520811', 'FL4520812', 'FL4520813', 'FL4520814', 'FL4520816', 'FL4520817', 'FL4520818', 'FL4520820', 'FL4520821', 'FL4520822', 'FL4520823', 'FL4520825', 'FL4520826', 'FL4520827', 'FL4520828', 'FL4520829', 'FL4520830', 'FL4520832', 'FL4520833', 'FL4520834', 'FL4520835', 'FL4520836', 'FL4562467', 'FL4562470', 'FL4562473', 'FL4562477', 'FL4562493', 'FL4562496', 'FL4562498', 'FL4562502', 'FL4562504', 'FL4562506', 'FL4562507', 'FL4562514', 'FL4562526', 'FL4562531', 'FL4562534', 'FL4562538', 'FL4562543', 'FL4562548', 'FL4431373', 'FL4431375', 'FL4431376', 'FL4431377', 'FL4431405', 'FL4431403', 'FL4534782','FL4534784','FL4534786','FL4534787','FL4534789','FL4548906','FL4548908','FL4548910','FL4548914','FL4548915','FL4548916','FL4548918','FL4548919','FL4548920','FL4548924','FL4581459','FL4581460','FL4581461','FL4581462','FL4581463','FL4581468','FL4581469','FL4581470','FL4581471','FL4581473','FL4581474','FL4581475','FL4581477','FL4581478','FL4581481','FL4544430','FL4544432','FL4544435','FL4544437','FL4544438','FL4544439','FL4544441','FL4544448','FL4528139','FL4528140','FL4528141','FL4528142','FL4528143','FL4528144','FL4527324','FL4527326','FL4527329','FL4527333','FL4527335','FL4530238'],
    'portraits': ['FL4549209', 'FL4564140', 'FL4549684', 'FL4545567', 'FL4488477', 'FL4545569', 'FL4534794', 'FL4510388', 'FL4513567', 'FL4513591', 'FL4513594', 'FL4468261', 'FL4531198', 'FL4531240', 'FL4517378', 'FL4517384', 'FL4529746', 'FL4512049', 'FL4512055', 'FL4485185', 'FL4487605', 'FL4487592', 'FL4485540', 'FL4484944', 'FL4484950', 'FL4481774', 'FL4481787', 'FL4478835', 'FL4486661', 'FL4486662', 'FL4474330', 'FL4474354', 'FL4480349', 'FL4480384', 'FL4486300', 'FL4473256', 'FL4474185', 'FL4474152', 'FL4479422', 'FL4479449', 'FL4474018', 'FL4472433', 'FL4479794', 'FL4466608', 'FL4466614', 'FL4450989', 'FL4489424', 'FL4480459', 'FL4588049', 'FL4492349', 'FL4502482', 'FL4491527', 'FL4444441', 'FL4490697', 'FL4433631', 'FL4434468', 'FL4430650', 'FL4430652', 'FL4468274', 'FL4529677', 'FL4532361', 'FL4495950', 'FL8797006', 'FL4522775', 'FL4517556', 'FL4517563', 'FL4518600', 'FL4515829', 'FL4515847', 'FL4519602', 'FL4424262', 'FL4424263', 'FL4424264', 'FL4424278', 'FL4424279', 'FL4588015', 'FL4588016', 'FL4588017', 'FL4537870', 'FL4537872', 'FL4537873', 'FL4537874', 'FL4537878', 'FL4537880', 'FL4537881', 'FL4537882', 'FL4537883', 'FL4537888', 'FL4537889', 'FL4537891', 'FL4537895', 'FL4537896', 'FL4537897', 'FL4537899', 'FL4537902', 'FL4537906', 'FL4537907', 'FL4537909', 'FL4537911', 'FL4540963', 'FL4540964', 'FL4540966', 'FL4540970', 'FL4540972', 'FL4540973', 'FL4540975', 'FL4539968', 'FL4539969', 'FL4539970', 'FL4539971', 'FL4539972', 'FL4539974', 'FL4539988', 'FL4539989', 'FL4490339', 'FL4538816', 'FL4538817', 'FL4538818', 'FL4538825', 'FL4538826', 'FL4538827', 'FL4538828', 'FL4538829', 'FL4538838', 'FL4538839', 'FL4538840', 'FL4538841']
}

Download the training images.

In [8]:
import os
from urllib.parse import urlparse
from tqdm import tqdm_notebook
import requests
# Download training images
for img_set in ['protests', 'portraits']:
    img_dir = os.path.join('tf_files', 'tribune', img_set)
    os.makedirs(img_dir, exist_ok=True)
    for img in tqdm_notebook(img_sets[img_set]):
        img_url = 'https://s3-ap-southeast-2.amazonaws.com/wraggetribune/images/500/{0}-500.jpg'.format(img)
        parsed = urlparse(img_url)
        filename = os.path.join(img_dir, os.path.basename(parsed.path))
        response = requests.get(img_url, stream=True)
        with open(filename, 'wb') as fd:
            for chunk in response.iter_content(chunk_size=128):
                fd.write(chunk)


In [9]:
ls tf_files/tribune
portraits/ protests/

Run this in a terminal, Jupyter doesn't allow background processes...

I'm assuming this won't be possible on Binder?

tensorboard --logdir tf_files/training_summaries &

Train the model

In [10]:
%%bash
IMAGE_SIZE=224
ARCHITECTURE="mobilenet_0.50_${IMAGE_SIZE}"

python -m scripts.retrain \
  --bottleneck_dir=tf_files/bottlenecks \
  --how_many_training_steps=500 \
  --model_dir=tf_files/models/ \
  --summaries_dir=tf_files/training_summaries/"${ARCHITECTURE}" \
  --output_graph=tf_files/tribune_graph.pb \
  --output_labels=tf_files/tribune_labels.txt \
  --architecture="${ARCHITECTURE}" \
  --image_dir=tf_files/tribune
INFO:tensorflow:Looking for images in 'portraits'
INFO:tensorflow:Looking for images in 'protests'
2018-10-28 14:42:43.281542: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA
INFO:tensorflow:100 bottleneck files created.
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4548906-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4548916-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4534787-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4528144-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4548920-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4544437-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4527333-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581473-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581463-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4534786-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4544435-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581461-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581471-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4534784-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581478-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581468-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4548914-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4527329-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581469-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581470-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581460-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581475-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4534789-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4527335-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4548918-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4548908-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4544438-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4528142-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4544439-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581474-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4544430-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4527324-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4548919-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4528140-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4548924-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4530238-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4544432-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581459-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4527326-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:200 bottleneck files created.
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4544441-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4528141-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4544448-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4548915-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4548910-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4534782-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581462-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581481-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4528143-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4528139-500.jpg_mobilenet_0.50_224.txt
INFO:tensorflow:Creating bottleneck at tf_files/bottlenecks/protests/FL4581477-500.jpg_mobilenet_0.50_224.txt
WARNING:tensorflow:From /Users/tim/mycode/glam-workbench/image-recognition/notebooks/tensorflow-for-poets-2/scripts/retrain.py:790: softmax_cross_entropy_with_logits (from tensorflow.python.ops.nn_ops) is deprecated and will be removed in a future version.
Instructions for updating:

Future major versions of TensorFlow will allow gradients to flow
into the labels input on backprop by default.

See `tf.nn.softmax_cross_entropy_with_logits_v2`.

INFO:tensorflow:2018-10-28 14:42:45.403470: Step 0: Train accuracy = 86.0%
INFO:tensorflow:2018-10-28 14:42:45.403937: Step 0: Cross entropy = 0.309668
INFO:tensorflow:2018-10-28 14:42:45.628682: Step 0: Validation accuracy = 92.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:45.994709: Step 10: Train accuracy = 94.0%
INFO:tensorflow:2018-10-28 14:42:45.994839: Step 10: Cross entropy = 0.257828
INFO:tensorflow:2018-10-28 14:42:46.029826: Step 10: Validation accuracy = 80.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:46.386835: Step 20: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:46.386965: Step 20: Cross entropy = 0.007310
INFO:tensorflow:2018-10-28 14:42:46.421428: Step 20: Validation accuracy = 95.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:46.782148: Step 30: Train accuracy = 98.0%
INFO:tensorflow:2018-10-28 14:42:46.782288: Step 30: Cross entropy = 0.052359
INFO:tensorflow:2018-10-28 14:42:46.817271: Step 30: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:47.180937: Step 40: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:47.181071: Step 40: Cross entropy = 0.004318
INFO:tensorflow:2018-10-28 14:42:47.218462: Step 40: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:47.580580: Step 50: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:47.580705: Step 50: Cross entropy = 0.007924
INFO:tensorflow:2018-10-28 14:42:47.615264: Step 50: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:47.971581: Step 60: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:47.971710: Step 60: Cross entropy = 0.007916
INFO:tensorflow:2018-10-28 14:42:48.006999: Step 60: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:48.363424: Step 70: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:48.363547: Step 70: Cross entropy = 0.002402
INFO:tensorflow:2018-10-28 14:42:48.397967: Step 70: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:48.752027: Step 80: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:48.752154: Step 80: Cross entropy = 0.002464
INFO:tensorflow:2018-10-28 14:42:48.787513: Step 80: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:49.141937: Step 90: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:49.142069: Step 90: Cross entropy = 0.002755
INFO:tensorflow:2018-10-28 14:42:49.176506: Step 90: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:49.527722: Step 100: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:49.527856: Step 100: Cross entropy = 0.003589
INFO:tensorflow:2018-10-28 14:42:49.562754: Step 100: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:49.916231: Step 110: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:49.916356: Step 110: Cross entropy = 0.001157
INFO:tensorflow:2018-10-28 14:42:49.950865: Step 110: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:50.305482: Step 120: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:50.305609: Step 120: Cross entropy = 0.001758
INFO:tensorflow:2018-10-28 14:42:50.340320: Step 120: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:50.693725: Step 130: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:50.693856: Step 130: Cross entropy = 0.002027
INFO:tensorflow:2018-10-28 14:42:50.728312: Step 130: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:51.088048: Step 140: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:51.088175: Step 140: Cross entropy = 0.001670
INFO:tensorflow:2018-10-28 14:42:51.122916: Step 140: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:51.476977: Step 150: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:51.477119: Step 150: Cross entropy = 0.000966
INFO:tensorflow:2018-10-28 14:42:51.511913: Step 150: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:51.864215: Step 160: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:51.864342: Step 160: Cross entropy = 0.000542
INFO:tensorflow:2018-10-28 14:42:51.898882: Step 160: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:52.254269: Step 170: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:52.254397: Step 170: Cross entropy = 0.001178
INFO:tensorflow:2018-10-28 14:42:52.289158: Step 170: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:52.655582: Step 180: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:52.655716: Step 180: Cross entropy = 0.001364
INFO:tensorflow:2018-10-28 14:42:52.692782: Step 180: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:53.062017: Step 190: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:53.062143: Step 190: Cross entropy = 0.000615
INFO:tensorflow:2018-10-28 14:42:53.097311: Step 190: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:53.451888: Step 200: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:53.452016: Step 200: Cross entropy = 0.001257
INFO:tensorflow:2018-10-28 14:42:53.486594: Step 200: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:53.846465: Step 210: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:53.846589: Step 210: Cross entropy = 0.000895
INFO:tensorflow:2018-10-28 14:42:53.881588: Step 210: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:54.245489: Step 220: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:54.245617: Step 220: Cross entropy = 0.000290
INFO:tensorflow:2018-10-28 14:42:54.280449: Step 220: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:54.642830: Step 230: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:54.642963: Step 230: Cross entropy = 0.001514
INFO:tensorflow:2018-10-28 14:42:54.677905: Step 230: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:55.031232: Step 240: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:55.031357: Step 240: Cross entropy = 0.000443
INFO:tensorflow:2018-10-28 14:42:55.065901: Step 240: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:55.429473: Step 250: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:55.429611: Step 250: Cross entropy = 0.000302
INFO:tensorflow:2018-10-28 14:42:55.464584: Step 250: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:55.827542: Step 260: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:55.827668: Step 260: Cross entropy = 0.000705
INFO:tensorflow:2018-10-28 14:42:55.862233: Step 260: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:56.236931: Step 270: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:56.237069: Step 270: Cross entropy = 0.000997
INFO:tensorflow:2018-10-28 14:42:56.273377: Step 270: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:56.644086: Step 280: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:56.644221: Step 280: Cross entropy = 0.000648
INFO:tensorflow:2018-10-28 14:42:56.682252: Step 280: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:57.057642: Step 290: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:57.057790: Step 290: Cross entropy = 0.001493
INFO:tensorflow:2018-10-28 14:42:57.093669: Step 290: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:57.485280: Step 300: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:57.485414: Step 300: Cross entropy = 0.000987
INFO:tensorflow:2018-10-28 14:42:57.521119: Step 300: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:57.880160: Step 310: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:57.880294: Step 310: Cross entropy = 0.000806
INFO:tensorflow:2018-10-28 14:42:57.915277: Step 310: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:58.269446: Step 320: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:58.269580: Step 320: Cross entropy = 0.000892
INFO:tensorflow:2018-10-28 14:42:58.304194: Step 320: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:58.665735: Step 330: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:58.665869: Step 330: Cross entropy = 0.000690
INFO:tensorflow:2018-10-28 14:42:58.701489: Step 330: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:59.063143: Step 340: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:59.063275: Step 340: Cross entropy = 0.000744
INFO:tensorflow:2018-10-28 14:42:59.098365: Step 340: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:59.462170: Step 350: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:59.462298: Step 350: Cross entropy = 0.000758
INFO:tensorflow:2018-10-28 14:42:59.497309: Step 350: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:42:59.864110: Step 360: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:42:59.864244: Step 360: Cross entropy = 0.000658
INFO:tensorflow:2018-10-28 14:42:59.899951: Step 360: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:00.260083: Step 370: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:00.260219: Step 370: Cross entropy = 0.000778
INFO:tensorflow:2018-10-28 14:43:00.297879: Step 370: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:00.656371: Step 380: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:00.656503: Step 380: Cross entropy = 0.000410
INFO:tensorflow:2018-10-28 14:43:00.691937: Step 380: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:01.059119: Step 390: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:01.059251: Step 390: Cross entropy = 0.000362
INFO:tensorflow:2018-10-28 14:43:01.093824: Step 390: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:01.447903: Step 400: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:01.448039: Step 400: Cross entropy = 0.000542
INFO:tensorflow:2018-10-28 14:43:01.482609: Step 400: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:01.836444: Step 410: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:01.836576: Step 410: Cross entropy = 0.000501
INFO:tensorflow:2018-10-28 14:43:01.871385: Step 410: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:02.229445: Step 420: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:02.229575: Step 420: Cross entropy = 0.000416
INFO:tensorflow:2018-10-28 14:43:02.263784: Step 420: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:02.620229: Step 430: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:02.620364: Step 430: Cross entropy = 0.000427
INFO:tensorflow:2018-10-28 14:43:02.655607: Step 430: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:03.019248: Step 440: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:03.019377: Step 440: Cross entropy = 0.000420
INFO:tensorflow:2018-10-28 14:43:03.054494: Step 440: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:03.410948: Step 450: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:03.411081: Step 450: Cross entropy = 0.000351
INFO:tensorflow:2018-10-28 14:43:03.445594: Step 450: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:03.801125: Step 460: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:03.801254: Step 460: Cross entropy = 0.000424
INFO:tensorflow:2018-10-28 14:43:03.836485: Step 460: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:04.194659: Step 470: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:04.194787: Step 470: Cross entropy = 0.000623
INFO:tensorflow:2018-10-28 14:43:04.229901: Step 470: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:04.585500: Step 480: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:04.585633: Step 480: Cross entropy = 0.000350
INFO:tensorflow:2018-10-28 14:43:04.621165: Step 480: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:04.976775: Step 490: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:04.976908: Step 490: Cross entropy = 0.000727
INFO:tensorflow:2018-10-28 14:43:05.012645: Step 490: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:2018-10-28 14:43:05.331810: Step 499: Train accuracy = 100.0%
INFO:tensorflow:2018-10-28 14:43:05.331937: Step 499: Cross entropy = 0.000311
INFO:tensorflow:2018-10-28 14:43:05.366962: Step 499: Validation accuracy = 100.0% (N=100)
INFO:tensorflow:Final test accuracy = 84.6% (N=26)
INFO:tensorflow:Froze 2 variables.
INFO:tensorflow:Converted 2 variables to const ops.

Test the trained model

First let's test against the training set.

In [11]:
# Make a list of all the test images
import os
import random
from IPython.display import display, HTML
imgs = []
data_dir = 'tf_files/tribune/'
for img_dir in [d for d in os.listdir(data_dir) if os.path.isdir(os.path.join(data_dir, d))]:
    for img in [i for i in os.listdir(os.path.join(data_dir, img_dir)) if i[-4:] == '.jpg']:
        imgs.append(os.path.join(data_dir, img_dir, img))    
In [12]:
# Choose one image at random
img = random.sample(imgs, 1)[0]
display(HTML('<img src="tensorflow-for-poets-2/{0}"><br>{0}'.format(img)))

tf_files/tribune/portraits/FL4444441-500.jpg
In [13]:
!python -m scripts.label_image --graph=tf_files/tribune_graph.pb --labels=tf_files/tribune_labels.txt --image=$img
2018-10-28 14:45:45.051535: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA

Evaluation time (1-image): 0.213s

portraits (score=1.00000)
protests (score=0.00000)

Test against a randomly selected image from the complete collection

Let's see how our model goes against images it's never seen before...

In [14]:
# Load Tribune images data
import pandas as pd
df = pd.read_csv('https://raw.githubusercontent.com/GLAM-Workbench/ozglam-data-records-of-resistance/master/data/images.csv')
In [15]:
# Set up a directory for test images
test_dir = os.path.join('tf_files', 'tribune_tests')
os.makedirs(test_dir, exist_ok=True)
images = df['images']
In [16]:
# get a random image
img = images.sample(1).iloc[0]
img_url = 'https://s3-ap-southeast-2.amazonaws.com/wraggetribune/images/500/{0}-500.jpg'.format(img)
filename = os.path.join(test_dir, '{}-500.jpg'.format(img))
response = requests.get(img_url, stream=True)
with open(filename, 'wb') as fd:
    for chunk in response.iter_content(chunk_size=128):
        fd.write(chunk)
display(HTML('<img src="tensorflow-for-poets-2/{0}"><br>{0}'.format(filename)))

tf_files/tribune_tests/FL4526748-500.jpg
In [17]:
!python -m scripts.label_image --graph=tf_files/tribune_graph.pb --labels=tf_files/tribune_labels.txt --image=$filename
2018-10-28 14:46:08.328867: I tensorflow/core/platform/cpu_feature_guard.cc:141] Your CPU supports instructions that this TensorFlow binary was not compiled to use: AVX2 FMA

Evaluation time (1-image): 0.208s

portraits (score=1.00000)
protests (score=0.00000)
In [ ]: