{"cells":[{"metadata":{"trusted":true},"cell_type":"code","source":"# submission score = 0.000って何？","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"!pip install keras==2.2.4\nimport numpy as np\nimport os\nimport pandas as pd\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom keras import callbacks\nfrom keras.utils.vis_utils import plot_model\nimport keras.backend as K\nimport tensorflow as tf\nfrom keras import initializers, layers, models\nfrom keras.utils import to_categorical","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"class Length(layers.Layer):\n    def call(self, inputs, **kwargs): \n        return K.sqrt(K.sum(K.square(inputs), -1)) \n \n    def compute_output_shape(self, input_shape):\n        return input_shape[:-1]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class Mask(layers.Layer):\n    def call(self, inputs, **kwargs):\n        if type(inputs) is list: \n            assert len(inputs) == 2\n            inputs, mask = inputs\n        else:\n            x = inputs\n \n            x = (x - K.max(x, 1, True)) / K.epsilon() + 1\n            mask = K.clip(x, 0, 1)\n \n        inputs_masked = K.batch_dot(inputs, mask, [1, 1])\n        return inputs_masked\n \n    def compute_output_shape(self, input_shape):\n        if type(input_shape[0]) is tuple:\n            return tuple([None, input_shape[0][-1]])\n        else:\n            return tuple([None, input_shape[-1]])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def squash(vectors, axis=-1):\n    s_squared_norm = K.sum(K.square(vectors), axis, keepdims=True)\n    scale = s_squared_norm / (1 + s_squared_norm) / K.sqrt(s_squared_norm)\n    return scale * vectors","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class CapsuleLayer(layers.Layer):\n    def __init__(self, num_capsule, dim_vector, num_routing=3,\n                 kernel_initializer='glorot_uniform',\n                 bias_initializer='zeros',\n                 **kwargs):\n        super(CapsuleLayer, self).__init__(**kwargs)\n        self.num_capsule = num_capsule\n        self.dim_vector = dim_vector\n        self.num_routing = num_routing\n        self.kernel_initializer = initializers.get(kernel_initializer)\n        self.bias_initializer = initializers.get(bias_initializer)\n \n    def build(self, input_shape):\n        #assert len(input_shape) >= 3,\n        self.input_num_capsule = input_shape[1]\n        self.input_dim_vector = input_shape[2]\n \n        self.W = self.add_weight(shape=[self.input_num_capsule, self.num_capsule, self.input_dim_vector, self.dim_vector],\n                                 initializer=self.kernel_initializer,\n                                 name='W')\n \n        self.bias = self.add_weight(shape=[1, self.input_num_capsule, self.num_capsule, 1, 1],\n                                    initializer=self.bias_initializer,\n                                    name='bias',\n                                    trainable=False)\n        self.built = True\n \n    def call(self, inputs, training=None):\n        inputs_expand = K.expand_dims(K.expand_dims(inputs, 2), 2)\n \n        inputs_tiled = K.tile(inputs_expand, [1, 1, self.num_capsule, 1, 1])\n \n        inputs_hat = tf.scan(lambda ac, x: K.batch_dot(x, self.W, [3, 2]),\n                             elems=inputs_tiled,\n                             initializer=K.zeros([self.input_num_capsule, self.num_capsule, 1, self.dim_vector]))\n \n        assert self.num_routing > 0, 'The num_routing should be > 0.'\n        for i in range(self.num_routing):\n            c = tf.nn.softmax(self.bias, dim=2)\n \n            outputs = squash(K.sum(c * inputs_hat, 1, keepdims=True))\n \n \n            if i != self.num_routing - 1:\n                self.bias += K.sum(inputs_hat * outputs, -1, keepdims=True)\n        return K.reshape(outputs, [-1, self.num_capsule, self.dim_vector])\n \n    def compute_output_shape(self, input_shape):\n        return tuple([None, self.num_capsule, self.dim_vector])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def PrimaryCap(inputs, dim_vector, n_channels, kernel_size, strides, padding):\n    output = layers.Conv2D(filters=dim_vector*n_channels, kernel_size=kernel_size, strides=strides, padding=padding)(inputs)\n    outputs = layers.Reshape(target_shape=[-1, dim_vector])(output)\n    return layers.Lambda(squash)(outputs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from keras import backend as K\ndef CapsNet(input_shape, n_class, num_routing):\n    x = layers.Input(shape=input_shape)\n    conv1 = layers.Conv2D(filters=256, kernel_size=9, strides=1, padding='valid', activation='relu', name='conv1')(x)\n    primarycaps = PrimaryCap(conv1, dim_vector=8, n_channels=32, kernel_size=9, strides=2, padding='valid')\n    digitcaps = CapsuleLayer(num_capsule=n_class, dim_vector=16, num_routing=num_routing, name='digitcaps')(primarycaps)\n    out_caps = Length(name='out_caps')(digitcaps)\n \n    y = layers.Input(shape=(n_class,))\n    masked = Mask()([digitcaps, y])\n    x_recon = layers.Dense(512, activation='relu')(masked)\n    x_recon = layers.Dense(1024, activation='relu')(x_recon)\n    x_recon = layers.Dense(width*breadth*3, activation='sigmoid')(x_recon)\n    x_recon = layers.Reshape(target_shape=[width, breadth, 3], name='out_recon')(x_recon)\n \n    return models.Model([x, y], [out_caps, x_recon])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def margin_loss(y_true, y_pred):\n    L = y_true * K.square(K.maximum(0., 0.9 - y_pred)) + \\\n        0.5 * (1 - y_true) * K.square(K.maximum(0., y_pred - 0.1))\n \n    return K.mean(K.sum(L, 1))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"width, breadth = 32, 32","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model = CapsNet(input_shape=[width, breadth, 3],\n                n_class=5,\n                num_routing=3)\nmodel.summary()\ntry:\n    plot_model(model, to_file='model.png', show_shapes=True)\nexcept Exception as e:\n    print('No fancy plot {}'.format(e))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# make data, train 16000, test 400 images\n# 1_left なら patientID = 1の人の左目の写真ということらしい","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"trainCSV = pd.read_csv('../input/diabetic-retinopathy-detection/trainLabels.csv')\ntrainCSV['PatientId'] = trainCSV['image'].map(lambda x: x.split('_')[0])\ntrainCSV['imagePath'] = trainCSV['image'].map(lambda x: os.path.join('../input/diabetic-retinopathy-detection/','{}.jpeg'.format(x)))\ntrainCSV['exists'] = trainCSV['imagePath'].map(os.path.exists)\ntrainCSV['leftorright'] = trainCSV['image'].map(lambda x: 'left' if x.split('_')[-1]=='left' else 'right')\ntrainCSV['label'] = trainCSV['level'].map(lambda x: to_categorical(x, 5))\ntrainCSV.dropna(inplace = True)\ntrainCSV = trainCSV[trainCSV['exists']]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"trainCSV.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from PIL import Image\nimport time\nimport sys","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"trainCSV.shape","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def transformImagetoArray(imagePathsList, width=480, breadth=480):\n    startTime = time.time()\n    imagesArrayList = []\n    for imagePath in imagePathsList:\n        image = np.array(Image.open(imagePath).resize((width, breadth)), np.float).reshape(width, breadth, 3)\n        imagesArrayList.append(image)\n    print (\"needed_time_for_makingArrays: {}\".format(time.time()-startTime) + \"[sec]\")\n    imagesArray = np.asarray(imagesArrayList)\n    print('imagesArray: {} MB'.format(str(sys.getsizeof(imagesArray) / (10**6))))\n    return imagesArray","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x = transformImagetoArray(list(trainCSV['imagePath']), width=width, breadth=breadth)\ny = np.asarray(list(trainCSV['label']))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from sklearn.model_selection import train_test_split\n\n#data = np.load('kaggle_retina_datasets.small.npz')\n#x, y = data['x'], data['y']\nx_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#x_train = x_train.reshape(1600, 480, 480, 3).astype('float32') / 255.\n#x_test = x_test.reshape(400, 480, 480, 3).astype('float32') / 255.\n#y_train = to_categorical(y_train.astype('float32'))\n#y_test = to_categorical(y_test.astype('float32'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import gc\ndel x\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('x train: %s' % str(x_train.shape))\nprint('x test: %s' % str(x_test.shape))\nprint('y train: %s' % str(y_train.shape))\nprint('y test: %s' % str(y_test.shape))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def train(model, data, epoch_size_frac=1.0, epochs=100, batch_size=64):\n \n    (x_train, y_train), (x_test, y_test) = data\n    \n    log = callbacks.CSVLogger('log.csv')\n    checkpoint = callbacks.ModelCheckpoint('weights-{epoch:02d}val_loss-{val_loss}.h5',\n                                           save_best_only=True, save_weights_only=False, verbose=1)\n    lr_decay = callbacks.LearningRateScheduler(schedule=lambda epoch: 0.001 * np.exp(-epoch / 10.))\n    # add early stopping\n    early_stopping = callbacks.EarlyStopping(monitor = 'val_loss', min_delta=0, patience = 5, verbose = 1)\n    model.compile(optimizer='adam',\n                  loss=[margin_loss, 'mse'],\n                  loss_weights=[1., 0.0005],\n                  metrics={'out_caps': 'accuracy'})\n \n    # -----------------------------------Begin: Training with data augmentation -----------------------------------#\n    def train_generator(x, y, batch_size, shift_fraction=0.):\n        train_datagen = ImageDataGenerator(width_shift_range=shift_fraction,\n                                           height_shift_range=shift_fraction)\n        generator = train_datagen.flow(x, y, batch_size=batch_size)\n        while 1:\n            x_batch, y_batch = generator.next()\n            yield ([x_batch, y_batch], [y_batch, x_batch])\n    # change max_queue_size from default 10 to 2\n    model.fit_generator(generator=train_generator(x_train, y_train, batch_size, 0.1),\n                        max_queue_size=2,\n                        steps_per_epoch=int(epoch_size_frac*y_train.shape[0] / batch_size),\n                        epochs=epochs,\n                        validation_data=[[x_test, y_test], [y_test, x_test]],\n                        callbacks=[log, checkpoint, lr_decay, early_stopping])\n    # -----------------------------------End: Training with data augmentation -----------------------------------#\n \n    model.save('trained_model.h5')\n    print('Trained model saved to \\'trained_model.h5\\'')\n \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train(model=model, data=((x_train, y_train), (x_test[:60], y_test[:60])), \n      epoch_size_frac = 1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def combine_images(generated_images):\n    num = generated_images.shape[0]\n    width = int(np.sqrt(num))\n    height = int(np.ceil(float(num)/width))\n    shape = generated_images.shape[1:3]\n    image = np.zeros((height*shape[0], width*shape[1]),\n                     dtype=generated_images.dtype)\n    for index, img in enumerate(generated_images):\n        i = int(index/width)\n        j = index % width\n        image[i*shape[0]:(i+1)*shape[0], j*shape[1]:(j+1)*shape[1]] = \\\n            img[:, :, 0]\n    return image\n \ndef test(model, data):\n    x_test, y_test = data\n    y_pred, x_recon = model.predict([x_test, y_test], batch_size=100)\n    print('-'*50)\n    print('Test acc:', np.sum(np.argmax(y_pred, 1) == np.argmax(y_test, 1))/y_test.shape[0])\n \n    import matplotlib.pyplot as plt\n    from PIL import Image\n \n    img = combine_images(np.concatenate([x_test[:50],x_recon[:50]]))\n    image = img * 255\n    Image.fromarray(image.astype(np.uint8)).save(\"real_and_recon.png\")\n    print()\n    print('Reconstructed images are saved to ./real_and_recon.png')\n    print('-'*50)\n    plt.imshow(plt.imread(\"real_and_recon.png\", ))\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"test(model=model, data=(x_test[:100], y_test[:100]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"del x_train, x_test, y_train, y_test\ngc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# DISK 容量的にkernel上でsubmissionを作るのは無理そう","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# なんかデータセットまとめてくれてる人いた","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(os.listdir('../input/resized-2015-2019-blindness-detection-images/resized test 15'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def predictandSaveSubmission():\n    imagePaths = os.listdir('../input/resized-2015-2019-blindness-detection-images/resized test 15')\n    predictionList = []\n    for imagePath in imagePaths:\n        tmp = [int(imagePath.split('.')[0].split('_')[0]), imagePath.split('.')[0].split('_')[1], imagePath.split('.')[0]]\n        imagePath = '../input/resized-2015-2019-blindness-detection-images/resized test 15/' + imagePath\n        imageArray = np.array([np.array(Image.open(imagePath).resize((width, breadth)), np.float).reshape(width, breadth, 3)])\n        y_pred, _ = model.predict_on_batch([imageArray, np.zeros((1, 5))])\n        #tmp += [int(np.argmax(y_pred))]\n        tmp += [1]\n        predictionList.append(tmp)\n    predictionList.sort(key=lambda x: (x[0], x[1]))\n    predictionDict = {}\n    predictionDict['image'] = [i[2] for i in predictionList]\n    predictionDict['level'] = [i[3] for i in predictionList]\n    \n    df_submission = pd.DataFrame(predictionDict)\n    df_submission.to_csv(\"submission.csv\",index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"predictandSaveSubmission()","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":1}