{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# This Python 3 environment comes with many helpful analytics libraries installed\n# It is defined by the kaggle/python Docker image: https://github.com/kaggle/docker-python\n# For example, here's several helpful packages to load\n\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\n# Input data files are available in the read-only \"../input/\" directory\n# For example, running this (by clicking run or pressing Shift+Enter) will list all files under the input directory\n\n# import os\n# for dirname, _, filenames in os.walk('/kaggle/input'):\n#     for filename in filenames:\n#         print(os.path.join(dirname, filename))\n\n# You can write up to 20GB to the current directory (/kaggle/working/) that gets preserved as output when you create a version using \"Save & Run All\" \n# You can also write temporary files to /kaggle/temp/, but they won't be saved outside of the current session","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"> # Load Data"},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Reading train rsna data...')\ntrain = pd.read_csv(\"../input/rsna-pneumonia-detection-challenge/stage_2_train_labels.csv\")\nprint(train.shape)\ntrain.head()","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"print('Reading train data...')\ntest = pd.read_csv(\"../input/chest-xray-anomaly-detection/train.csv\")\nprint(test.shape)\ntest.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print('Reading sample data...')\nss = pd.read_csv(\"../input/chest-xray-anomaly-detection/sample_submission.csv\")\nprint(ss.shape)\nss.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import cv2\nfrom PIL import Image\nimport pydicom\nfrom skimage.transform import resize\n\ndef get_dicom_images():\n    inputdir = '../input/rsna-pneumonia-detection-challenge/stage_2_train_images/'\n    train_list = [ f for f in  os.listdir(inputdir)]\n    images = []\n    for f in train_list[:2000]:   # remove \"[:10]\" to convert all images \n        ds = pydicom.read_file(inputdir + f) # read dicom image\n        img = ds.pixel_array # get image array\n    #     img = np.expand_dims(ds.pixel_array,axis=0)  \n        img = resize(img, (32, 32, 3), mode='reflect')\n        images.append(img)\n    #     cv2.imwrite(outdir + f.replace('.dcm','.png'),img) # write png image\n    return np.array(images)\n\n\ndef get_normal_images(filenames):\n    path = \"../input/chest-xray-anomaly-detection/images/\"\n    images = []\n    for filename in filenames['fileName']:\n        path_img = path + filename\n        img_array = np.array(Image.open(path_img))\n        img_array = resize(img_array, (32, 32, 3), mode='reflect')\n        images.append(img_array)\n    return np.array(images)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# import the necessary packages\nfrom tensorflow.keras.layers import BatchNormalization\nfrom tensorflow.keras.layers import Conv2D\nfrom tensorflow.keras.layers import Conv2DTranspose\nfrom tensorflow.keras.layers import LeakyReLU\nfrom tensorflow.keras.layers import Activation\nfrom tensorflow.keras.layers import Flatten\nfrom tensorflow.keras.layers import Dense\nfrom tensorflow.keras.layers import Reshape\nfrom tensorflow.keras.layers import Input\nfrom tensorflow.keras.models import Model\nfrom tensorflow.keras import backend as K\nimport numpy as np\nclass ConvAutoencoder:\n\t@staticmethod\n\tdef build(width, height, depth, filters=(32, 64), latentDim=16):\n\t\t# initialize the input shape to be \"channels last\" along with\n\t\t# the channels dimension itself\n\t\t# channels dimension itself\n\t\tinputShape = (height, width, depth)\n\t\tchanDim = -1\n\t\t# define the input to the encoder\n\t\tinputs = Input(shape=inputShape)\n\t\tx = inputs\n\t\t# loop over the number of filters\n\t\tfor f in filters:\n\t\t\t# apply a CONV => RELU => BN operation\n\t\t\tx = Conv2D(f, (3, 3), strides=2, padding=\"same\")(x)\n\t\t\tx = LeakyReLU(alpha=0.2)(x)\n\t\t\tx = BatchNormalization(axis=chanDim)(x)\n\t\t# flatten the network and then construct our latent vector\n\t\tvolumeSize = K.int_shape(x)\n\t\tx = Flatten()(x)\n\t\tlatent = Dense(latentDim)(x)\n\t\t# build the encoder model\n\t\tencoder = Model(inputs, latent, name=\"encoder\")\n           \n\t\t# start building the decoder model which will accept the\n\t\t# output of the encoder as its inputs\n\t\tlatentInputs = Input(shape=(latentDim,))\n\t\tx = Dense(np.prod(volumeSize[1:]))(latentInputs)\n\t\tx = Reshape((volumeSize[1], volumeSize[2], volumeSize[3]))(x)\n\n\t\t# loop over our number of filters again, but this time in\n\t\t# reverse order\n\t\tfor f in filters[::-1]:\n\t\t\t# apply a CONV_TRANSPOSE => RELU => BN operation\n\t\t\tx = Conv2DTranspose(f, (3, 3), strides=2,\n\t\t\t\tpadding=\"same\")(x)\n\t\t\tx = LeakyReLU(alpha=0.2)(x)\n\t\t\tx = BatchNormalization(axis=chanDim)(x)\n\n\t\t# apply a single CONV_TRANSPOSE layer used to recover the\n\t\t# original depth of the image\n\t\tx = Conv2DTranspose(depth, (3, 3), padding=\"same\")(x)\n\t\toutputs = Activation(\"sigmoid\")(x)\n\n\t\t# build the decoder model\n\t\tdecoder = Model(latentInputs, outputs, name=\"decoder\")\n\n\t\t# our autoencoder is the encoder + decoder\n\t\tautoencoder = Model(inputs, decoder(encoder(inputs)),\n\t\t\tname=\"autoencoder\")\n\n\t\t# return a 3-tuple of the encoder, decoder, and autoencoder\n\t\treturn (encoder, decoder, autoencoder)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import matplotlib\nmatplotlib.use(\"Agg\")\n# import the necessary packages\n# from pyimagesearch.convautoencoder import ConvAutoencoder\nfrom tensorflow.keras.optimizers import Adam\nfrom tensorflow.keras.datasets import mnist\nfrom sklearn.model_selection import train_test_split\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport argparse\nimport random\nimport pickle\nimport cv2","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def visualize_predictions(decoded, gt, samples=10):\n\t# initialize our list of output images\n\toutputs = None\n\t# loop over our number of output samples\n\tfor i in range(0, samples):\n\t\t# grab the original image and reconstructed image\n\t\toriginal = (gt[i] * 255).astype(\"uint8\")\n\t\trecon = (decoded[i] * 255).astype(\"uint8\")\n\t\t# stack the original and reconstructed image side-by-side\n\t\toutput = np.hstack([original, recon])\n\t\t# if the outputs array is empty, initialize it as the current\n\t\t# side-by-side image display\n\t\tif outputs is None:\n\t\t\toutputs = output\n\t\t# otherwise, vertically stack the outputs\n\t\telse:\n\t\t\toutputs = np.vstack([outputs, output])\n\t# return the output images\n\treturn outputs","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# initialize the number of epochs to train for, initial learning rate,\n# and batch size\nEPOCHS = 20\nINIT_LR = 1e-3\nBS = 32\n# build our unsupervised dataset of images with a small amount of\n# contamination (i.e., anomalies) added into it\n# add a channel dimension to every image in the dataset, then scale\n# the pixel intensities to the range [0, 1]\nimages = get_normal_images(test)\n# images = np.expand_dims(train_images, axis=-1)\nimages = images.astype(\"float32\") / 255.0\n\n# construct the training and testing split\n(trainX, testX) = train_test_split(images, test_size=0.2,\n\trandom_state=42)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(trainX.shape)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(\"[INFO] building autoencoder...\")\n(encoder, decoder, autoencoder) = ConvAutoencoder.build(32, 32, 3)\nopt = Adam(lr=INIT_LR, decay=INIT_LR / EPOCHS)\nautoencoder.compile(loss=\"mse\", optimizer=opt)\n# train the convolutional autoencoder\nH = autoencoder.fit(\n\ttrainX, trainX,\n\tvalidation_data=(testX, testX),\n\tepochs=EPOCHS,\n\tbatch_size=BS)\n# use the convolutional autoencoder to make predictions on the\n# testing images, construct the visualization, and then save it\n# to disk\nprint(\"[INFO] making predictions...\")\ndecoded = autoencoder.predict(testX)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"vis = visualize_predictions(decoded, testX)\ncv2.imwrite(\"vis.png\", vis)\nimg_array = np.array(Image.open('./vis.png'))\nplt.imshow(img_array)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# construct a plot that plots and saves the training history\nN = np.arange(0, EPOCHS)\nplt.style.use(\"ggplot\")\nplt.figure()\nplt.plot(N, H.history[\"loss\"], label=\"train_loss\")\nplt.plot(N, H.history[\"val_loss\"], label=\"val_loss\")\nplt.title(\"Training Loss\")\nplt.xlabel(\"Epoch #\")\nplt.ylabel(\"Loss\")\nplt.legend(loc=\"lower left\")\nplt.show()\n# plt.savefig(\"plot.jpg\")\n\n# serialize the image data to disk\nprint(\"[INFO] saving image data...\")\nf = open(\"images.pickle\", \"wb\")\nf.write(pickle.dumps(images))\nf.close()\n\n# serialize the autoencoder model to disk\nprint(\"[INFO] saving autoencoder...\")\nautoencoder.save(\"autoencoder.model\", save_format=\"h5\")","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# import the necessary packages\nfrom tensorflow.keras.models import load_model\nimport numpy as np\nimport argparse\nimport pickle\nimport cv2\n\n# load the model and image data from disk\nprint(\"[INFO] loading autoencoder and image data...\")\nautoencoder = load_model(\"autoencoder.model\")\n# images = pickle.loads(open(\"images.pickle\", \"rb\").read())\n# make predictions on our image data and initialize our list of\n# reconstruction errors\ntest_images = get_normal_images(ss)\ndecoded = autoencoder.predict(test_images)\nerrors = []\n# loop over all original images and their corresponding\n# reconstructions\nfor (image, recon) in zip(test_images, decoded):\n\t# compute the mean squared error between the ground-truth image\n\t# and the reconstructed image, then add it to our list of errors\n\tmse = np.mean((image - recon) ** 2)\n\terrors.append(mse)\n    \n# compute the q-th quantile of the errors which serves as our\n# threshold to identify anomalies -- any data point that our model\n# reconstructed with > threshold error will be marked as an outlier\nthresh = np.quantile(errors, 0.89)\nidxs = np.where(np.array(errors) >= thresh)[0]\nprint(\"[INFO] mse threshold: {}\".format(thresh))\nprint(\"[INFO] {} outliers found\".format(len(idxs)))    ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(idxs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission = []\nfor i, filename in enumerate(ss.fileName):\n    if i in idxs:\n        submission.append([filename, 1])\n    else:\n        submission.append([filename, 0])\ndf = pd.DataFrame(submission, columns = ['fileName', 'anomaly']) \ndf.to_csv('test_predictions.csv', index=False)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# # initialize the outputs array\n# outputs = None\n\n# # loop over the indexes of images with a high mean squared error term\n# for i in idxs:\n# \t# grab the original image and reconstructed image\n# \toriginal = (images[i] * 255).astype(\"uint8\")\n# \trecon = (decoded[i] * 255).astype(\"uint8\")\n\n# \t# stack the original and reconstructed image side-by-side\n# \toutput = np.hstack([original, recon])\n\n# \t# if the outputs array is empty, initialize it as the current\n# \t# side-by-side image display\n# \tif outputs is None:\n# \t\toutputs = output\n\n# \t# otherwise, vertically stack the outputs\n# \telse:\n# \t\toutputs = np.vstack([outputs, output])\n\n# # show the output visualization\n# cv2.imshow(\"Output\", outputs)\n# cv2.waitKey(0)","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}