{"cells":[{"cell_type":"markdown","metadata":{"_cell_guid":"4c1518a6-76a0-44f4-0f56-3231efc206fa"},"source":"Public Leader-board of 0.89094\n===================================================="},{"cell_type":"markdown","metadata":{"_cell_guid":"f75ef7fc-84d2-8ed9-4617-9cf09facb4e0"},"source":"Save train and test images to normalized numpy arrays once for running multiple neural network configuration tests"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"f6b29b0e-075c-3ee0-6f23-2cbec877ae5b"},"outputs":[],"source":"import numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport os, platform, glob, itertools\nfrom multiprocessing import Pool, cpu_count\nfrom PIL import ImageFilter, ImageStat, Image, ImageDraw\nfrom sklearn.preprocessing import LabelEncoder\nimport cv2\n\n#--------------#\n\nfrom keras.wrappers.scikit_learn import KerasClassifier\nfrom keras.models import Sequential\nfrom keras.layers.normalization import BatchNormalization\nfrom keras.layers.core import Dense, Dropout, Flatten, Activation\nfrom keras.layers.convolutional import Convolution2D, ZeroPadding2D, MaxPooling2D\nfrom keras import optimizers\nfrom keras.preprocessing.image import ImageDataGenerator\nfrom sklearn.model_selection import train_test_split\nfrom keras import backend as K"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"7dbb49cf-7725-75f3-1b33-8c216b45c069"},"outputs":[],"source":"# derived code from:\n# https://www.kaggle.com/kambarakun/intel-mobileodt-cervical-cancer-screening/how-to-start-with-python-on-colfax-cluster\n\n'''\nProcessing functions\n'''\ndef load_gry_img(abspath_img):\n    img = cv2.cvtColor(cv2.imread(abspath_img), cv2.COLOR_BGR2GRAY)\n    return img\n\ndef show_img(abspath_img):\n    matplotlib.pyplot.imshow(sub_func_load_img(abspath_img))\n    matplotlib.pyplot.show()\n\n# Orient images to be portriate\ndef orient_img(img):\n    if img.shape[0] >= img.shape[1]:\n        return img\n    else:\n        return np.rot90(img)\n\n# make all images same size\ndef resize_img_same_ratio(img):\n    if img.shape[0] / 640.0 >= img.shape[1] / 480.0:\n        # (640, *, 3)\n        img_resized = cv2.resize(img, (int(640.0 * img.shape[1] / img.shape[0]), 640)) \n    else:\n        # (*, 480, 3)\n        img_resized = cv2.resize(img, (480, int(480.0 * img.shape[0] / img.shape[1]))) \n    return img_resized\n\n# fill in blank space with black\ndef fill_img(img):\n    if img.shape[0] == 640:\n        int_resize_1 = img.shape[1]\n        int_fill_1 = (480 - int_resize_1 ) // 2 #floor\n        int_fill_2 =  480 - int_resize_1 - int_fill_1\n        numpy_fill_1 = np.zeros((640, int_fill_1, 3),dtype=np.uint8)\n        numpy_fill_2 = np.zeros((640, int_fill_2, 3), dtype=np.uint8)\n        img_filled = np.concatenate((numpy_fill_1, img, numpy_fill_1), axis=1)\n\n    elif img.shape[1] == 480:\n        int_resize_0 = img.shape[0]\n        int_fill_1 = (640 - int_resize_0 ) // 2 #floor\n        int_fill_2 = 640 - int_resize_0 - int_fill_1\n        numpy_fill_1 = np.zeros((int_fill_1, 480, 3), dtype=np.uint8)\n        numpy_fill_2 = np.zeros((int_fill_2, 480, 3), dtype=np.uint8)\n        img_filled = np.concatenate((numpy_fill_1, img, numpy_fill_1), axis=0)\n\n    else:\n        raise ValueError\n\n    return img_filled\n\n# normalize pixel intesity to account for shadows and intesity variability within photo\ndef normalize_img(img):\n    img_data = img.astype('float32')\n    return img_data / 255  #255 comes from RBG format"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"5dec1f36-b8e4-c853-74b4-8988a26f393b"},"outputs":[],"source":"''' \ninput - filename\noutput - processed image\n\nReads image converts to RGB color\nFlips image to portriat orientation\nResizes image to match orientation\nFills in blanks with black\nResizes image to input size based on arguement using bilinear interpolation\n'''\ndef get_im_cv2(path, input_pic_dims = (32,32)):\n    img = cv2.imread(path)\n    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n    img = orient_img(img)\n    img = resize_img_same_ratio(img)\n    img = fill_img(img)\n    img = resize_img_same_ratio(img)\n    resized = cv2.resize(img, input_pic_dims, cv2.INTER_LINEAR)\n    return [path, resized]\n\ndef normalize_image_features(paths):\n    imf_d = {}\n    p = Pool(cpu_count())\n    ret = p.map(get_im_cv2, paths)\n    for i in range(len(ret)):\n        imf_d[ret[i][0]] = ret[i][1]\n    ret = []\n    fdata = [imf_d[f] for f in paths]\n    fdata = np.array(fdata, dtype=np.uint8)\n    fdata = fdata.transpose((0, 3, 1, 2))\n    fdata = fdata.astype('float32')\n    fdata = fdata / 255\n    return fdata\n"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"a1198dd8-c496-abab-fcef-fe95fa0ca1d6"},"outputs":[],"source":"def im_multi(path):\n    try:\n        im_stats_im_ = Image.open(path)\n        return [path, {'size': im_stats_im_.size}]\n    except:\n        print(path)\n        return [path, {'size': [0,0]}]\n\ndef im_stats(im_stats_df):\n    im_stats_d = {}\n    p = Pool(cpu_count())\n    ret = p.map(im_multi, im_stats_df['path'])\n    for i in range(len(ret)):\n        im_stats_d[ret[i][0]] = ret[i][1]\n    im_stats_df['size'] = im_stats_df['path'].map(lambda x: ' '.join(str(s) for s in im_stats_d[x]['size']))\n    return im_stats_df"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"6466c479-a18f-00b5-98a0-6f105de69b3e"},"outputs":[],"source":"def run_processing():\n    train = glob.glob('../input/train/**/*.jpg') #+ glob.glob('../input/additional/**/*.jpg')\n    cols= ['type','image','path']\n     #limit for Kaggle Demo\n    train = pd.DataFrame([[p.split('/')[3],p.split('/')[4],p] for p in train], columns = cols)[::3] \n    train = im_stats(train)\n    train = train[train['size'] != '0 0'].reset_index(drop=True) #remove bad images\n    train_data = normalize_image_features(train['path'])\n    np.save('train.npy', train_data, allow_pickle=True, fix_imports=True)\n\n    le = LabelEncoder()\n    train_target = le.fit_transform(train['type'].values)\n    print(le.classes_) #in case not 1 to 3 order\n    np.save('train_target.npy', train_target, allow_pickle=True, fix_imports=True)\n\n    test = glob.glob('../input/test/*.jpg')\n    #[::20] #limit for Kaggle Demo\n    test = pd.DataFrame([[p.split('/')[3],p] for p in test], columns = ['image','path'])[::20] \n    test_data = normalize_image_features(test['path'])\n    np.save('test.npy', test_data, allow_pickle=True, fix_imports=True)\n\n    test_id = test.image.values\n    np.save('test_id.npy', test_id, allow_pickle=True, fix_imports=True)"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"29024b29-3870-b431-b732-4ef60c118773"},"outputs":[],"source":"def create_model(opt_='adamax', input_dims):\n    model = Sequential()\n#    model.add(BatchNormalization(axis=1, momentum=0.9, epsilon=0.001, center=True, scale=True))\n    #inputshape (batch_size, steps, input_dim)\n    model.add(Convolution2D(filters=8, kernel_size=3,strides=(1,1), input_shape=input_dims) #use input_shape=(3, 64, 64)\n    model.add(Activation('relu'))              \n    model.add(BatchNormalization(axis=1, momentum=0.9, epsilon=0.001, center=True, scale=True))\n    model.add(Convolution2D(filters=8, kernel_size=3,strides=(1,1), input_shape=input_dims) #use input_shape=(3, 64, 64)\n    model.add(Activation('relu'))  \n    model.add(Convolution2D(filters=8, kernel_size=3,strides=(1,1), input_shape=input_dims) #use input_shape=(3, 64, 64)\n\n    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), dim_ordering='tf'))\n    model.add(Convolution2D(filters=4, kernel_size=3, activation='relu'))\n    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), dim_ordering='tf'))\n    model.add(Dropout(0.5))\n    \n    model.add(Flatten())\n    model.add(Dense(20, activation='tanh'))\n    model.add(Dropout(0.25))\n    model.add(Dense(12, activation='tanh'))\n    model.add(Dense(3, activation='softmax'))\n\n    model.compile(optimizer=opt_, loss='sparse_categorical_crossentropy', metrics=['accuracy']) \n    return model"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"9383ea59-45d5-08d7-631f-72c8504b0c9e"},"outputs":[],"source":"def create_model(opt_='adamax', input_dims):\n    model = Sequential()\n#    model.add(BatchNormalization(axis=1, momentum=0.9, epsilon=0.001, center=True, scale=True))\n    #inputshape (batch_size, steps, input_dim)\n    model.add(Convolution2D(filters=8, kernel_size=3,strides=(1,1), input_shape=input_dims) #use input_shape=(3, 64, 64)\n    model.add(Activation('relu'))              \n    model.add(BatchNormalization(axis=1, momentum=0.9, epsilon=0.001, center=True, scale=True))\n    model.add(Convolution2D(filters=8, kernel_size=3,strides=(1,1), input_shape=input_dims) #use input_shape=(3, 64, 64)\n    model.add(Activation('relu'))  \n    model.add(Convolution2D(filters=8, kernel_size=3,strides=(1,1), input_shape=input_dims) #use input_shape=(3, 64, 64)\n\n    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), dim_ordering='tf'))\n    model.add(Convolution2D(filters=4, kernel_size=3, activation='relu'))\n    model.add(MaxPooling2D(pool_size=(2, 2), strides=(2, 2), dim_ordering='tf'))\n    model.add(Dropout(0.5))\n    \n    model.add(Flatten())\n    model.add(Dense(20, activation='tanh'))\n    model.add(Dropout(0.25))\n    model.add(Dense(12, activation='tanh'))\n    model.add(Dense(3, activation='softmax'))\n\n    model.compile(optimizer=opt_, loss='sparse_categorical_crossentropy', metrics=['accuracy']) \n    return model"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"fc97dacc-9466-b369-b190-c979de910ba7"},"outputs":[],"source":"def run_model():\n    # Setting state variables\n    K.set_image_dim_ordering('th')\n    K.set_floatx('float32')\n    np.random.seed(17)\n\n    # Reading in data\n    train_data = np.load('train.npy')\n    train_target = np.load('train_target.npy')\n\n    # Cross fold training\n    x_train,x_val_train,y_train,y_val_train = train_test_split(train_data,train_target,test_size=0.4, random_state=17)\n\n    # Data Augmentation\n    datagen = ImageDataGenerator(\n        rotation_range=40,\n        width_shift_range=0.2,\n        height_shift_range=0.2,\n        shear_range=0.2,\n        zoom_range=0.2,\n        horizontal_flip=True,\n        fill_mode='nearest')\n    datagen = ImageDataGenerator(rotation_range=0.3, zoom_range=0.3)\n\n    datagen.fit(train_data)\n\n    # Run Model\n    model = create_model()\n    model.fit_generator(datagen.flow(x_train,y_train, batch_size=15, shuffle=True), nb_epoch=200, samples_per_epoch=len(x_train), verbose=20, validation_data=(x_val_train, y_val_train))\n    return model"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"d1ce9481-0f89-dbe1-81b6-68a925dc24dd"},"outputs":[],"source":"def create_submission(model, fn='submission.csv'):\n    # Load test data\n    test_data = np.load('test.npy')\n    test_id = np.load('test_id.npy')\n    \n    # create submission\n    pred = model.predict_proba(test_data)\n    df = pd.DataFrame(pred, columns=['Type_1','Type_2','Type_3'])\n    df['image_name'] = test_id\n    df = df[['image_name','Type_1','Type_2','Type_3']]\n    df.to_csv(fn, index=False)\n    \ndef print_submission(results = 'submission.csv'):\n    with open(results) as fn:\n        for line in fn:\n            print(line[1:])"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"6cb823c1-dc3a-8de1-15c2-b0b9aa444161"},"outputs":[],"source":"def main():\n    #----Model Params-----#\n    batch_size = 32\n    epochs = 200\n    data_augmentation = True\n    # most deep learning libraries run faster with input size of square 2^n\n    dim = 2^6 #2^6 = 64\n    input_shape = (dim, dim)\n    \n    \n    full_run = False\n    if full_run:\n        run_processing()\n        model = run_model()\n        create_submission(model)\n        print_submission()\n    else:\n        model = run_model()\n        create_submission(model)"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"0981b119-5847-df95-42e6-9225f26143cf"},"outputs":[],"source":"main()\n"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"7b4a37ed-de91-24d1-094e-1daa832b87cd"},"outputs":[],"source":"print_submission()"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"9bda1864-9583-6b73-2e70-0c5c1d9c2c82"},"outputs":[],"source":"with open('submission.csv') as fn:\n    for line in fn:\n        print(line)"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"fed38dcd-41f6-225c-64d0-f0c7a419c5df"},"outputs":[],"source":"# not tested yet\ndef processing_helper(img_list):\n    p = Pool(cpu_count())\n    output = p.map(process_img, img_list) \n    img_array = np.array(output)\n    p.close()\n    p.join()\n    return img_array\n\n\ndef process_images_parallel(dirs_df_dir, fn):\n    img_df = pd.read_csv(dirs_df_dir+fn+'.csv', header=0)\n    img_paths = img_df['paths'].head()\n    print('created df')\n    arr = processing_helper(img_paths)\n    return arr"},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"4b05ad78-cbd3-5f1c-1ef8-1b56b2bf996c"},"outputs":[],"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"b953c4d0-4414-922c-4fe9-7487ea837b14"},"outputs":[],"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"60b68a39-87f2-fe7a-90a6-2023d653e301"},"outputs":[],"source":""},{"cell_type":"code","execution_count":null,"metadata":{"_cell_guid":"0e85f01f-317d-f043-4cfc-18069a415e1d"},"outputs":[],"source":""}],"metadata":{"_change_revision":0,"_is_fork":false,"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.6.0"}},"nbformat":4,"nbformat_minor":0}