In [1]:
# windows only hack for graphviz path 
import os
for path in os.environ['PATH'].split(os.pathsep):
    if path.endswith("Library\\bin"):
        os.environ['PATH']+=os.pathsep+os.path.join(path, 'graphviz')

In [2]:
# 設定環境變數來控制 keras, theano
os.environ['KERAS_BACKEND']="tensorflow"
#os.environ['THEANO_FLAGS']="floatX=float32, device=cuda"

In [3]:
import keras
from keras.models import Sequential
from PIL import Image
import numpy as np


Using TensorFlow backend.

In [4]:
import keras.backend as K
# 設定 channels_first 或 channels_last
K.set_image_data_format('channels_last')

In [5]:
base_model = keras.applications.vgg16.VGG16(weights='imagenet',  include_top=False, input_shape=(224,224,3))

In [6]:
from keras.layers import GlobalAveragePooling2D, Dense, Dropout, BatchNormalization
from keras.models import Model
_ = base_model.get_layer("block5_conv3").output
_ = GlobalAveragePooling2D()(_)
_ = Dense(512, activation='relu')(_)
_ = Dropout(0.5)(_)
# 2 個輸出
predictions = Dense(2, activation='softmax')(_)
# 這是我們的 model
model = Model(inputs=base_model.input, outputs=predictions)

# 將原來的模型設定成不可訓練,只訓練上面的兩層 dense layers
for layer in base_model.layers:
    layer.trainable = False

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

In [7]:
import numpy as np
def preprocess_X(X):
    return X[:,:,:,::-1].astype('float32')-[103.939,116.779,123.68]
train_X=np.zeros(shape=(20000,224,224,3), dtype="uint8")
for i in range(10000):
    img = Image.open("../Week06/train/cat.%d.jpg"%i).resize((224,224))
    train_X[2*i] =np.array(img)    
    img = Image.open("../Week06/train/dog.%d.jpg"%i).resize((224,224))    
    train_X[2*i+1] = np.array(img)
train_y=[0,1]*10000  
train_Y = np.eye(2)[train_y]

In [8]:
def generate(X, Y):    
    while 1:
        idx = np.random.choice(18000, size=32, replace=False)    
        _X = preprocess_X(X[idx])
        _Y = Y[idx]
        yield (_X, _Y)
v_data = (preprocess_X(train_X[18000:]), train_Y[18000:])
model.fit_generator(generate(train_X, train_Y), steps_per_epoch=500, epochs=10, validation_data=v_data)


Epoch 1/10
500/500 [==============================] - 169s - loss: 0.1330 - acc: 0.9692 - val_loss: 0.0755 - val_acc: 0.9775
Epoch 2/10
500/500 [==============================] - 172s - loss: 0.0561 - acc: 0.9826 - val_loss: 0.0734 - val_acc: 0.9805
Epoch 3/10
500/500 [==============================] - 172s - loss: 0.0450 - acc: 0.9846 - val_loss: 0.0604 - val_acc: 0.9840
Epoch 4/10
500/500 [==============================] - 172s - loss: 0.0340 - acc: 0.9882 - val_loss: 0.0681 - val_acc: 0.9810
Epoch 5/10
500/500 [==============================] - 172s - loss: 0.0312 - acc: 0.9894 - val_loss: 0.0617 - val_acc: 0.9835
Epoch 6/10
500/500 [==============================] - 172s - loss: 0.0324 - acc: 0.9894 - val_loss: 0.0581 - val_acc: 0.9845
Epoch 7/10
500/500 [==============================] - 173s - loss: 0.0294 - acc: 0.9914 - val_loss: 0.0530 - val_acc: 0.9860
Epoch 8/10
500/500 [==============================] - 173s - loss: 0.0315 - acc: 0.9904 - val_loss: 0.0582 - val_acc: 0.9865
Epoch 9/10
500/500 [==============================] - 172s - loss: 0.0314 - acc: 0.9900 - val_loss: 0.0611 - val_acc: 0.9840
Epoch 10/10
500/500 [==============================] - 174s - loss: 0.0217 - acc: 0.9922 - val_loss: 0.0653 - val_acc: 0.9860
Out[8]:
<keras.callbacks.History at 0x7feca42276d8>

往前微調幾層


In [9]:
for n in ["block5_conv1", "block5_conv2", "block5_conv3"]:
    model.get_layer(n).trainable = True
from keras.optimizers import Adam
model.compile(optimizer=Adam(lr=0.0001), loss='categorical_crossentropy', metrics=["accuracy"])
model.fit_generator(generate(train_X, train_Y), steps_per_epoch=500, epochs=10, validation_data=v_data)


Epoch 1/10
500/500 [==============================] - 195s - loss: 0.0804 - acc: 0.9742 - val_loss: 0.0618 - val_acc: 0.9795
Epoch 2/10
 39/500 [=>............................] - ETA: 161s - loss: 0.0610 - acc: 0.9784
---------------------------------------------------------------------------
KeyboardInterrupt                         Traceback (most recent call last)
<ipython-input-9-410cb4581c2f> in <module>()
      3 from keras.optimizers import Adam
      4 model.compile(optimizer=Adam(lr=0.0001), loss='categorical_crossentropy', metrics=["accuracy"])
----> 5 model.fit_generator(generate(train_X, train_Y), steps_per_epoch=500, epochs=10, validation_data=v_data)

/usr/local/lib/python3.5/dist-packages/keras/legacy/interfaces.py in wrapper(*args, **kwargs)
     86                 warnings.warn('Update your `' + object_name +
     87                               '` call to the Keras 2 API: ' + signature, stacklevel=2)
---> 88             return func(*args, **kwargs)
     89         wrapper._legacy_support_signature = inspect.getargspec(func)
     90         return wrapper

/usr/local/lib/python3.5/dist-packages/keras/engine/training.py in fit_generator(self, generator, steps_per_epoch, epochs, verbose, callbacks, validation_data, validation_steps, class_weight, max_q_size, workers, pickle_safe, initial_epoch)
   1874                     outs = self.train_on_batch(x, y,
   1875                                                sample_weight=sample_weight,
-> 1876                                                class_weight=class_weight)
   1877 
   1878                     if not isinstance(outs, list):

/usr/local/lib/python3.5/dist-packages/keras/engine/training.py in train_on_batch(self, x, y, sample_weight, class_weight)
   1618             ins = x + y + sample_weights
   1619         self._make_train_function()
-> 1620         outputs = self.train_function(ins)
   1621         if len(outputs) == 1:
   1622             return outputs[0]

/usr/local/lib/python3.5/dist-packages/keras/backend/tensorflow_backend.py in __call__(self, inputs)
   2071         session = get_session()
   2072         updated = session.run(self.outputs + [self.updates_op],
-> 2073                               feed_dict=feed_dict)
   2074         return updated[:len(self.outputs)]
   2075 

/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py in run(self, fetches, feed_dict, options, run_metadata)
    765     try:
    766       result = self._run(None, fetches, feed_dict, options_ptr,
--> 767                          run_metadata_ptr)
    768       if run_metadata:
    769         proto_data = tf_session.TF_GetBuffer(run_metadata_ptr)

/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py in _run(self, handle, fetches, feed_dict, options, run_metadata)
    963     if final_fetches or final_targets:
    964       results = self._do_run(handle, final_targets, final_fetches,
--> 965                              feed_dict_string, options, run_metadata)
    966     else:
    967       results = []

/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py in _do_run(self, handle, target_list, fetch_list, feed_dict, options, run_metadata)
   1013     if handle is None:
   1014       return self._do_call(_run_fn, self._session, feed_dict, fetch_list,
-> 1015                            target_list, options, run_metadata)
   1016     else:
   1017       return self._do_call(_prun_fn, self._session, handle, feed_dict,

/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py in _do_call(self, fn, *args)
   1020   def _do_call(self, fn, *args):
   1021     try:
-> 1022       return fn(*args)
   1023     except errors.OpError as e:
   1024       message = compat.as_text(e.message)

/usr/local/lib/python3.5/dist-packages/tensorflow/python/client/session.py in _run_fn(session, feed_dict, fetch_list, target_list, options, run_metadata)
   1002         return tf_session.TF_Run(session, options,
   1003                                  feed_dict, fetch_list, target_list,
-> 1004                                  status, run_metadata)
   1005 
   1006     def _prun_fn(session, handle, feed_dict, fetch_list):

KeyboardInterrupt: 

In [ ]: