{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport random, re, math, time\n\nfrom os.path import join \n\nimport tensorflow as tf\nimport tensorflow.keras.backend as K\n#import tensorflow_addons as tfa\n\nfrom tqdm.keras import TqdmCallback\n\nfrom PIL import Image\n\nimport matplotlib.pyplot as plt\n\nfrom sklearn.model_selection import KFold\n\nfrom sklearn.utils.class_weight import compute_class_weight\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.metrics import classification_report\n\n\n\nimport plotly\nimport plotly.graph_objects as go\nimport plotly.express as px\nfrom plotly.subplots import make_subplots\n\nrandom.seed(a=42)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"AUTO = tf.data.experimental.AUTOTUNE\nstrategy = tf.distribute.get_strategy()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"BASEPATH = \"../input/digit-recognizer\"\nCLASSES = 10\nSIZE = 28\nCNT_TRAIN = 42000\nCNT_TEST = 28000\n\ndf = pd.read_csv(join(BASEPATH, 'train.csv')).values.astype(np.uint8)\nx_train_all = df[:,1:].reshape((CNT_TRAIN, SIZE, SIZE))\ny_train_all = df[:,0]\n\ndf = pd.read_csv(join(BASEPATH, 'test.csv')).values.astype(np.uint8)\nx_test = df.reshape((CNT_TEST, SIZE, SIZE))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_mat(rotation, shear, height_zoom, width_zoom, height_shift, width_shift):\n    # returns 3x3 transformmatrix which transforms indicies\n        \n    # CONVERT DEGREES TO RADIANS\n    rotation = math.pi * rotation / 180.\n    shear = math.pi * shear / 180.\n    \n    # ROTATION MATRIX\n    c1 = tf.math.cos(rotation)\n    s1 = tf.math.sin(rotation)\n    one = tf.constant([1],dtype='float32')\n    zero = tf.constant([0],dtype='float32')\n    rotation_matrix = tf.reshape( tf.concat([c1,s1,zero, -s1,c1,zero, zero,zero,one],axis=0),[3,3] )\n        \n    # SHEAR MATRIX\n    c2 = tf.math.cos(shear)\n    s2 = tf.math.sin(shear)\n    shear_matrix = tf.reshape( tf.concat([one,s2,zero, zero,c2,zero, zero,zero,one],axis=0),[3,3] )    \n    \n    # ZOOM MATRIX\n    zoom_matrix = tf.reshape( tf.concat([one/height_zoom,zero,zero, zero,one/width_zoom,zero, zero,zero,one],axis=0),[3,3] )\n    \n    # SHIFT MATRIX\n    shift_matrix = tf.reshape( tf.concat([one,zero,height_shift, zero,one,width_shift, zero,zero,one],axis=0),[3,3] )\n    \n    return K.dot(K.dot(rotation_matrix, shear_matrix), K.dot(zoom_matrix, shift_matrix))\n\ndef transform(image):\n    \n    # input image - is one image of size [dim,dim,3] not a batch of [b,dim,dim,3]\n    # output - image randomly rotated, sheared, zoomed, and shifted\n    DIM = SIZE*2\n    XDIM = DIM%2 #fix for size 331\n    \n    rot = 15.0 * tf.random.normal([1],dtype='float32')\n    shr = 12.0 * tf.random.normal([1],dtype='float32') \n    h_zoom = 1.0 + tf.random.normal([1],dtype='float32')/8.0\n    w_zoom = 1.0 + tf.random.normal([1],dtype='float32')/8.0\n    h_shift = 4.0 * tf.random.normal([1],dtype='float32') \n    w_shift = 4.0 * tf.random.normal([1],dtype='float32') \n\n    # GET TRANSFORMATION MATRIX\n    m = get_mat(rot,shr,h_zoom,w_zoom,h_shift,w_shift) \n\n    # LIST DESTINATION PIXEL INDICES\n    x = tf.repeat( tf.range(DIM//2,-DIM//2,-1), DIM )\n    y = tf.tile( tf.range(-DIM//2,DIM//2),[DIM] )\n    z = tf.ones([DIM*DIM],dtype='int32')\n    idx = tf.stack( [x,y,z] )\n    \n    # ROTATE DESTINATION PIXELS ONTO ORIGIN PIXELS\n    idx2 = K.dot(m,tf.cast(idx,dtype='float32'))\n    idx2 = K.cast(idx2,dtype='int32')\n    idx2 = K.clip(idx2,-DIM//2+XDIM+1,DIM//2)\n    \n    # FIND ORIGIN PIXEL VALUES           \n    idx3 = tf.stack( [DIM//2-idx2[0,], DIM//2-1+idx2[1,]] )\n    d = tf.gather_nd(image,tf.transpose(idx3))\n        \n    return tf.reshape(d,[DIM,DIM])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def prepare_image(img, label=None, augment=True):\n    img = tf.cast(img, dtype=tf.float32)\n    img = img / 255\n    \n    img = tf.reshape(img, (SIZE, SIZE, 1))\n    img = tf.image.resize(img, (SIZE*2,SIZE*2), method=tf.image.ResizeMethod.NEAREST_NEIGHBOR, antialias=True)\n            \n    if augment:\n        if 0.9 > tf.random.uniform([1], minval=0, maxval=1):\n            img = transform(img)\n            \n    img = tf.reshape(img, (SIZE*2, SIZE*2, 1))\n    img = tf.image.resize(img, (SIZE,SIZE), method=tf.image.ResizeMethod.BILINEAR, antialias=True)\n    img = tf.reshape(img, (SIZE, SIZE))\n    \n    if label is None:\n        return img\n    else:\n        #label = tf.cast(label, dtype=tf.float32)\n        label = tf.one_hot(label, CLASSES)\n        return img, label","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def getTrainDataset(x, y, augment = True, shuffle = True):\n    ds = tf.data.Dataset.from_tensor_slices((x, y)) \n    ds = ds.repeat()\n    \n    if shuffle:\n        ds = ds.shuffle(1024)\n        \n    \n    ds = ds.map(lambda img, label: prepare_image(img, label, augment=augment), num_parallel_calls=AUTO)\n    ds = ds.batch(32*strategy.num_replicas_in_sync)\n    ds = ds.prefetch(AUTO)\n    return ds","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"it = iter(getTrainDataset(x_train_all, y_train_all).unbatch())\n\nimg = Image.new(mode='L', size=(32*SIZE+31, 10*SIZE+9), color=30)\nfor i in range(32*10):    \n    (img2, label) = next(it)\n    img2 = img2*255\n    ix = i % 32\n    iy= i // 32\n    img1 = Image.fromarray(img2.numpy().reshape((SIZE,SIZE)).astype(np.uint8))\n    img.paste(img1, (ix*SIZE+ix, iy*SIZE+iy))\n        \ndisplay(img)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def getTestDataset(x, augment = False, repeat = False):\n    ds = tf.data.Dataset.from_tensor_slices((x)) \n    \n    if repeat:\n        ds = ds.repeat()     \n        \n    ds = ds.map(lambda img: prepare_image(img, augment=augment), num_parallel_calls=AUTO)\n    ds = ds.batch(32*strategy.num_replicas_in_sync)\n    ds = ds.prefetch(AUTO)\n    return ds\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"it = iter(getTestDataset(x_test).unbatch())\n\nimg = Image.new(mode='L', size=(32*SIZE+31, 10*SIZE+9), color=30)\nfor i in range(32*10):    \n    img2 = next(it)\n    img2 = img2*255\n    ix = i % 32\n    iy= i // 32\n    img1 = Image.fromarray(img2.numpy().reshape((SIZE,SIZE)).astype(np.uint8))\n    img.paste(img1, (ix*SIZE+ix, iy*SIZE+iy))\n        \ndisplay(img)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_model():\n    cur = tf.keras.Input(shape=(SIZE, SIZE), name=\"imgIn\")\n    model_input = cur\n    \n    cur = tf.keras.layers.Reshape((SIZE, SIZE, 1))(cur)\n\n    cur = tf.keras.layers.Conv2D(16, kernel_size=(7, 7), activation=\"relu\")(cur)\n    cur = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(cur)\n    \n    cur = tf.keras.layers.Conv2D(32, kernel_size=(3, 3), activation=\"relu\")(cur)\n    cur = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(cur)\n    \n    cur = tf.keras.layers.Flatten()(cur)\n    #cur = tf.keras.layers.Dropout(0.5)(cur)\n    cur = tf.keras.layers.Dense(CLASSES, activation=\"softmax\")(cur)      \n    \n    model = tf.keras.Model(model_input, cur, name='aNetwork')\n    \n    return model\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def get_model_2():\n    cur = tf.keras.Input(shape=(SIZE, SIZE), name=\"imgIn\")\n    model_input = cur\n    \n    cur = tf.keras.layers.Reshape((SIZE, SIZE, 1))(cur)\n\n    cur = tf.keras.layers.Conv2D(32, kernel_size=(7, 7), activation=\"relu\")(cur)\n    cur = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(cur)\n    \n    cur = tf.keras.layers.Conv2D(64, kernel_size=(3, 3), activation=\"relu\")(cur)\n    cur = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(cur)\n    \n    cur = tf.keras.layers.Conv2D(128, kernel_size=(3, 3), activation=\"relu\")(cur)\n    cur = tf.keras.layers.MaxPooling2D(pool_size=(2, 2))(cur)\n    \n    cur = tf.keras.layers.Flatten()(cur)\n    #cur = tf.keras.layers.Dropout(0.5)(cur)\n    cur = tf.keras.layers.Dense(CLASSES, activation=\"softmax\")(cur)      \n    \n    model = tf.keras.Model(model_input, cur, name='aNetwork')\n    \n    return model","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"strategy = tf.distribute.get_strategy()\n\nwith strategy.scope():\n    model = get_model()\n \n    model.compile(\n        optimizer = 'adam',\n        #loss = tf.keras.losses.SparseCategoricalCrossentropy(),\n        loss = tf.keras.losses.CategoricalCrossentropy(),\n        metrics=['categorical_accuracy']\n    )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"model.summary()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"def visualizeCnnFilters(w):\n    w = w.numpy()\n    (tx, ty, bits, cnt) = w.shape\n    w = w/w.std()\n    w = w/2\n    np.clip(w, -1, 1, out=w)\n    w = (w*127+127).astype(np.uint8)\n    tilesy = (cnt-1) // 10\n    img = Image.new(mode='L', size=(tx*10+9, ty*(tilesy+1)+tilesy))\n    \n    for i in range(cnt):\n        ix = i % 10\n        iy = i // 10\n        img2 = Image.fromarray(w[:,:,0,i])\n        img.paste(img2, (ix*tx+ix, iy*ty+iy))\n     \n    return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"display(visualizeCnnFilters(model.weights[0]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x_train, x_val, y_train, y_val = train_test_split(x_train_all, y_train_all, test_size=0.33, random_state=42)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ds_train = getTrainDataset(x_train, y_train, augment = True)\nds_val = getTrainDataset(x_val, y_val, augment = False)\n\nstepsTrain = len(y_train) / (32 * strategy.num_replicas_in_sync)\nstepsVal   = len(y_val) / (32 * strategy.num_replicas_in_sync)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"history = model.fit(ds_train, \n                    validation_data=ds_val, \n                    verbose = 1,\n                    steps_per_epoch=stepsTrain, \n                    validation_steps=stepsVal, \n                    epochs=5)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"display(visualizeCnnFilters(model.weights[0]))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"ds_test = getTestDataset(x_test)\nprobs_test = model.predict(ds_test, verbose=1)\ny_test = np.argmax(probs_test, axis=1)\nsubmission = pd.read_csv(join(BASEPATH, 'sample_submission.csv'))\nsubmission['Label'] = y_test\nsubmission.to_csv('submission.csv', index = False)\n!head submission.csv","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","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":4}