{"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"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":13333,"databundleVersionId":862146,"sourceType":"competition"}],"dockerImageVersionId":29852,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport cv2\nimport keras\nimport operator\nimport matplotlib.pyplot as plt\n\nfrom keras.preprocessing.image import save_img\nfrom keras.preprocessing.image import ImageDataGenerator, array_to_img, img_to_array, load_img\nfrom keras.models import Sequential\nfrom keras.layers import Conv2D, MaxPooling2D\nfrom keras.layers.convolutional import Convolution2D, MaxPooling2D, ZeroPadding2D\nfrom keras.layers import Activation, Dropout, Flatten, Dense\nfrom keras import optimizers\nfrom keras.optimizers import SGD\nfrom keras import applications\nfrom keras import backend as K\nfrom keras.models import Model\nfrom keras import utils","metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"os.mkdir('../working/train')\ntrain_path = '../working/train/'\n\nos.mkdir(train_path + 'fish')\nos.mkdir(train_path + 'flower')\nos.mkdir(train_path + 'gravel')\nos.mkdir(train_path + 'sugar')\n\nos.mkdir('../working/test')\ntest_path = '../working/test/'\n\nos.mkdir(test_path + 'fish')\nos.mkdir(test_path + 'flower')\nos.mkdir(test_path + 'gravel')\nos.mkdir(test_path + 'sugar')","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_df = pd.read_csv('../input/understanding_cloud_organization/train.csv')\n\ntrain_df = train_df[train_df['EncodedPixels'].notnull()]\n\ntrain_df.insert(0, 'Image_ID', train_df['Image_Label'].apply(lambda x: x.split('_')[0]))\n\ntrain_df.insert(0, 'Original_information', train_df['Image_Label'])\n\ntrain_df['Image_Label'] = train_df['Image_Label'].apply(lambda x: x.split('_')[1])\n\ntrain_df.rename(columns = {'EncodedPixels': 'Encoded_Pixels'}, inplace = True)\n\ntrain_df.head()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def decode_rle(rle_string, width, height):\n    rows = height\n    columns = width\n    \n    rle_numbers = [int(number_string) for number_string in rle_string.split(' ')]\n    rle_pairs = np.array(rle_numbers).reshape(-1, 2)\n    \n    image = np.zeros(rows * columns, dtype = np.uint8)\n    \n    for index, length in rle_pairs:\n        index -= 1\n        image[index: index + length] = 255\n        \n    return image.reshape(columns, rows).T\n\ndef get_first(array):\n    index = None\n    for i, item in enumerate(array):\n        if(item > 0):\n            index = i\n            break\n    return index\n\ndef get_last(array):\n    index = None\n    for i in range(0, len(array))[::-1]:\n        if(array[i] > 0):\n            index = i\n            break\n    return index + 1","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"image_shape = (1400, 2100)\n\ntrain_fish_count = 0\ntrain_flower_count = 0\ntrain_gravel_count = 0\ntrain_sugar_count = 0\n\ntest_fish_count = 0\ntest_flower_count = 0\ntest_gravel_count = 0\ntest_sugar_count = 0\n\nimages = train_df['Original_information']\n\nfor original_information in images:\n    print('Processing: ', original_information)\n    \n    image_ID = original_information.split('_')[0]\n    image_class = original_information.split('_')[1]\n    \n    if(image_class == 'Fish'):\n        if(train_fish_count < 500):\n            train_fish_count += 1\n            output_path = train_path + 'fish/' + 'fish' + str(train_fish_count) + '.png'\n        elif(test_fish_count < 200):\n            test_fish_count += 1\n            output_path = test_path + 'fish/' + 'fish' + str(test_fish_count) + '.png'\n        else:\n            continue\n        \n    elif(image_class == 'Flower'):\n        if(train_flower_count < 500):\n            train_flower_count += 1\n            output_path = train_path + 'flower/' + 'flower' + str(train_flower_count) + '.png'\n        elif(test_flower_count < 200):\n            test_flower_count += 1\n            output_path = test_path + 'flower/' + 'flower' + str(test_flower_count) + '.png'\n        else:\n            continue\n        \n    elif(image_class == 'Gravel'):\n        if(train_gravel_count < 500):\n            train_gravel_count += 1\n            output_path = train_path + 'gravel/' + 'gravel' + str(train_gravel_count) + '.png'\n        elif(test_gravel_count < 200):\n            test_gravel_count += 1\n            output_path = test_path + 'gravel/' + 'gravel' + str(test_gravel_count) + '.png'\n        else:\n            continue\n            \n    elif(image_class == 'Sugar'):\n        if(train_sugar_count < 500):\n            train_sugar_count += 1\n            output_path = train_path + 'sugar/' + 'sugar' + str(train_sugar_count) + '.png'\n        elif(test_sugar_count < 200):\n            test_sugar_count += 1\n            output_path = test_path + 'sugar/' + 'sugar' + str(test_sugar_count) + '.png'\n        else:\n            continue\n    \n    image_mask = np.zeros(image_shape)\n    \n    encoded_masks = train_df.loc[train_df['Original_information'] == original_information, 'Encoded_Pixels'].tolist()\n    \n    for rle_string in encoded_masks:\n        if not pd.isnull(rle_string):\n            image_mask += decode_rle(rle_string, 2100, 1400)\n            \n    image_mask = image_mask.astype(np.uint8)\n    \n    original_image = cv2.imread('../input/understanding_cloud_organization/train_images/' + str(image_ID))\n    \n    modified_image = cv2.add(original_image, np.zeros(np.shape(original_image), dtype = np.uint8), mask = image_mask)\n    \n    (modified_Bcomponent, modified_Gcomponent, modified_Rcomponent) = cv2.split(modified_image)\n\n    Bcomponent = modified_Bcomponent[~np.all(modified_Bcomponent == 0, axis = 1)]\n    Gcomponent = modified_Gcomponent[~np.all(modified_Gcomponent == 0, axis = 1)]\n    Rcomponent = modified_Rcomponent[~np.all(modified_Rcomponent == 0, axis = 1)]\n    \n    first_indexs = [get_first(Bcomponent[0]), get_first(Gcomponent[0]), get_first(Rcomponent[0])]\n    last_indexs = [get_last(Bcomponent[0]), get_last(Gcomponent[0]), get_last(Rcomponent[0])]\n    \n    _, first_index = min(enumerate(first_indexs), key = operator.itemgetter(1))\n    _, last_index = max(enumerate(last_indexs), key = operator.itemgetter(1))\n    \n    Bcomponent = Bcomponent[:, first_index:last_index]\n    Gcomponent = Gcomponent[:, first_index:last_index]\n    Rcomponent = Rcomponent[:, first_index:last_index]\n\n    cropped_image = cv2.merge([Bcomponent, Gcomponent, Rcomponent])\n    \n    cropped_image = cv2.resize(cropped_image, (224, 224))\n    \n    save_img(output_path, cropped_image)","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# dimensions of the images\nimg_width = 224\nimg_height = 224\n\n# Amounts of train data and test data\ntrain_size = 2000\ntest_size = 800\n\n# Times of data iteration\n# As the number of epochs increases, the number of weight updates in neural network increases\n# Model changes from underfitting to overfitting\nepochs = 50\n\n# Amount of data pass through the neural network at a time\nbatch_size = 16","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"Self designed CNN\nAccuracy ≈ .73 Test_Accuracy ≈ .63\n\nPretrained VGG16\nAccuracy ≈ .98 Test_Accuracy ≈ .83\n\nPretrained VGG16 None Weights\nAccuracy ≈ .92 Test_Accuracy ≈ .84\n\nFine tuned VGG16\nAccuracy ≈ .84 Test_Accuracy ≈ .69\n\nFine tuned VGG16 None Weights\nAccuracy ≈ .60 Test_Accuracy ≈ .62\n\nInception Resnet V2\nAccuracy ≈ .97 Test_Accuracy ≈ .84\n\nResnet50\nAccuracy ≈ .81 Test_Accuracy ≈ .80\n\nVGG19\nAccuracy ≈ .95 Test_Accuracy ≈ .84\n\nInception V3\nAccuracy ≈ .98 Test_Accuracy ≈ .83\n\nXception\nAccuracy ≈ .98 Test_Accuracy ≈ .84\n\nDesnet 201\nAccuracy ≈ .98 Test_Accuracy ≈ .84\n\nMobileNetV2\nAccuracy ≈ .99 Test_Accuracy ≈ .84","metadata":{}},{"cell_type":"code","source":"if K.image_data_format() == 'channels_first':\n    input_shape = (3, img_width, img_height)\nelse:\n    input_shape = (img_width, img_height, 3)\n\n# A simple convolutional neural network implementation consisting of three convolutional neural layers and three maximum pooling layers\n# Sequential model is the simplest linear model, which implements the linear stacking of multiple network layers.\nmodel = Sequential()\n\n# Convolutional neural layer\n# The activation function is to increase the non-linearity of the neural network model, \n# so is responsible for mapping the input of the neuron to the output.\n# 'relu' activation function means The Rectified Linear Unit, which is f(x) = max(0, x).\n\n# First layer\n# Input data size should be claimed in first layer\nmodel.add(Conv2D(32, (3, 3), input_shape = input_shape))\nmodel.add(Activation('relu'))\nmodel.add(MaxPooling2D(pool_size = (2, 2)))\n\n# Second layer\nmodel.add(Conv2D(32, (3, 3)))\nmodel.add(Activation('relu'))\nmodel.add(MaxPooling2D(pool_size = (2, 2)))\n\n# Third layer\nmodel.add(Conv2D(64, (3, 3)))\nmodel.add(Activation('relu'))\nmodel.add(MaxPooling2D(pool_size = (2, 2)))\n\n# Then 2 fully-connected layers.\n# Dense function represents fully-connection layer\n\n# Flatten is generally used between the convolutional neural layer and the fully connected layer to flatten data, \n# to reshape the input to a one-dimensional array\nmodel.add(Flatten())\nmodel.add(Dense(64))\nmodel.add(Activation('relu'))\n\n# Dropout can prevent neurons from working probabilistically, thereby preventing overfitting\n# Activation function sigmoid can map input into interval of 0 and 1\nmodel.add(Dropout(0.5))\nmodel.add(Dense(4))\nmodel.add(Activation('softmax'))\n\n# compile the model\n# The loss function is used to determine the adjustment range of the parameter, \n# The greater the loss, the more parameters need to be adjusted and vice versa.\n# Cross entropy is a loss function used to determine how close the actual output is to the expected output.\n# Root Mean Square Prop optimizer is used to achieve minimum loss\n# 'accuracy' is always used to evaluate the performance of classification problems.\nmodel.compile(\n    loss = 'categorical_crossentropy',\n    optimizer = 'rmsprop',\n    metrics = ['accuracy']\n)\n\n# data proprocess\n# Apply transformations to image data to prevent repeating training the same image more than once\n# rescale maps RGB coefficients from 0 to 255 to 0 to 1\n# shear is used to apply shear transformations\n# zoom is for randomly zooming inside pictures\n# horizontal_flip is for randomly flipping half of the images horizontally\n\n# Augmentation configuration for training data\ntrain_data_generator = ImageDataGenerator(\n    rescale = 1. / 255,\n    shear_range = 0.2,\n    zoom_range = 0.2,\n    horizontal_flip = True\n)\n\n# Augmentation configuration for training data\ntest_data_generator = ImageDataGenerator(\n    rescale = 1./ 255\n)\n\n# generator to load image file and do augumentation then generate input data\n# training data\ntrain_generator = train_data_generator.flow_from_directory(\n    train_path,\n    # resize\n    target_size = (img_width, img_height),\n    batch_size = batch_size,\n    class_mode = 'categorical'\n)\n\n# testing data\ntest_generator = test_data_generator.flow_from_directory(\n    test_path,\n    # resize\n    target_size = (img_width, img_height),\n    batch_size = batch_size,\n    class_mode = 'categorical'\n)\n\n# Set parameters then train and test model\nhistory_1 = model.fit_generator(\n    train_generator,\n    # Times to train all data in single iteration \n    steps_per_epoch = train_size // batch_size,\n    # Iteration times\n    epochs = epochs,\n    # test\n    validation_data = test_generator,\n    validation_steps = test_size // batch_size\n)\n\nmodel.save_weights('first_try.h5')\n\n# Plot the accruacy, loss, train accuracy and train loss\nloss = history_1.history['loss']\nval_loss = history_1.history['val_loss']\naccuracy = history_1.history['accuracy']\nval_accuracy = history_1.history['val_accuracy']\n\nplt.style.use(\"ggplot\")\nn = epochs\n\nplt.figure()\nplt.suptitle('Train Loss and Accuracy') \nplt.xlabel('Epoch')\nplt.ylabel('Loss/Accuracy')\nplt.plot(np.arange(0, n), loss, label = 'train_loss')\nplt.plot(np.arange(0, n), accuracy, label = 'train_accuracy')\n\nplt.legend()\n\nplt.figure()\nplt.suptitle('Validation Loss and Accuracy') \nplt.xlabel('Epoch')\nplt.ylabel('Loss/Accuracy')\nplt.plot(np.arange(0, n), val_loss, label = 'val_loss')\nplt.plot(np.arange(0, n), val_accuracy, label = 'val_accuracy')\n\nplt.legend()\n\nplt.figure()\nplt.title('Loss') \nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.plot(np.arange(0, n), loss, label = 'train_loss')\nplt.plot(np.arange(0, n), val_loss, label = 'val_loss')\n\nplt.legend()\n\nplt.figure()\nplt.title('Accuracy') \nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.plot(np.arange(0, n), accuracy, label = 'train_accuracy')\nplt.plot(np.arange(0, n), val_accuracy, label = 'val_accuracy')\n\nplt.legend()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# use the VGG16 architecture, pre-trained model on the ImageNet dataset to improve accuracy\n# VGG16 architecture contains 5 convolutional blocks and 1 fully-connected block.\n# Conv block 1: 2 convolutional layers and 1 maxpolling layer, with 64 output fileters\n# Conv block 2: 2 convolutional layers and 1 maxpolling layer, with 128 output fileters\n# Conv block 3: 3 convolutional layers and 1 maxpolling layer, with 256 output fileters\n# Conv block 4: 3 convolutional layers and 1 maxpolling layer, with 512 output fileters\n# Conv block 5: 3 convolutional layers and 1 maxpolling layer, with 512 output fileters\n\n# full-connected block: 3 full-connected layers\n\ntop_model_weights_path = 'bottleneck_fc_model.h5'\n\n# Try to save the convolutional parts model results as bottleneck features in order to switch fc block later.\n\ndef save_bottleneck_features():\n    \n    data_generator = ImageDataGenerator(\n        rescale = 1. / 255\n    )\n    \n    # build VGG16 model\n    #model = applications.VGG16(include_top = False, weights = None)\n    # model = applications.VGG16(include_top = False, weights = 'imagenet')\n    # model = applications.InceptionResNetV2(include_top = False, weights = 'imagenet')\n    # model = applications.InceptionResNetV2(include_top = False, weights = None)\n    # model = applications.ResNet50(include_top = False, weights = 'imagenet')\n    # model = applications.VGG19(include_top = False, weights = 'imagenet')\n    # model = applications.InceptionV3(include_top = False, weights = 'imagenet')\n    # model = applications.Xception(include_top = False, weights = 'imagenet')\n    # model = applications.DenseNet201(include_top = False, weights = 'imagenet')\n    model = applications.MobileNetV2(include_top = False, weights = 'imagenet')\n    \n    generator = data_generator.flow_from_directory(\n        train_path,\n        target_size = (img_width, img_height),\n        batch_size = batch_size,\n        class_mode = None,\n        shuffle = False\n    )\n    \n    bottleneck_features_train = model.predict_generator(generator, train_size // batch_size)\n    \n    # 'wb' instead of 'w'\n    np.save(\n        open('bottleneck_features_train.npy', 'wb'),\n        bottleneck_features_train\n    )\n    \n    generator = data_generator.flow_from_directory(\n        test_path,\n        target_size = (img_width, img_height),\n        batch_size = batch_size,\n        class_mode = None,\n        shuffle = False\n    )\n    \n    bottleneck_features_test = model.predict_generator(generator, test_size // batch_size)\n    \n    # 'wb' instead of 'w'\n    np.save(\n        open('bottleneck_features_test.npy', 'wb'),\n        bottleneck_features_test\n    )\n    \nsave_bottleneck_features()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# build full-connected block\ndef train_top_model():\n    # 'rb' instead of 'r'\n    train_data = np.load(open('bottleneck_features_train.npy', 'rb'))\n    train_labels = np.array([0] * int((train_size / 4)) + [1] * int((train_size / 4)) + [2] * int((train_size / 4)) + [3] * int((train_size / 4)))\n    train_labels = utils.to_categorical(train_labels, 4)\n    # 'rb' instead of 'r'\n    test_data = np.load(open('bottleneck_features_test.npy', 'rb'))\n    test_labels = np.array([0] * int((test_size / 4)) + [1] * int((test_size / 4)) + [2] * int((test_size / 4)) + [3] * int((test_size / 4)))\n    test_labels = utils.to_categorical(test_labels, 4)\n    \n    model = Sequential()\n    \n    model.add(Flatten(input_shape=train_data.shape[1:]))\n    model.add(Dense(256, activation = 'relu'))\n    model.add(Dropout(0.5))\n    model.add(Dense(4, activation = 'softmax'))\n    \n    model.compile(optimizer = 'rmsprop', loss = 'categorical_crossentropy', metrics = ['accuracy'])\n    \n    history_2 = model.fit(\n        train_data,\n        train_labels,\n        epochs = epochs,\n        batch_size = batch_size,\n        validation_data = (test_data, test_labels)\n    )\n    \n    model.save_weights(top_model_weights_path)\n    \n    # Plot the accruacy, loss, train accuracy and train loss\n    loss = history_2.history['loss']\n    val_loss = history_2.history['val_loss']\n    accuracy = history_2.history['accuracy']\n    val_accuracy = history_2.history['val_accuracy']\n    \n    plt.style.use(\"ggplot\")\n    n = epochs\n\n    plt.figure()\n    plt.suptitle('Train Loss and Accuracy') \n    plt.xlabel('Epoch')\n    plt.ylabel('Loss/Accuracy')\n    plt.plot(np.arange(0, n), loss, label = 'train_loss')\n    plt.plot(np.arange(0, n), accuracy, label = 'train_accuracy')\n    \n    plt.legend()\n    \n    plt.figure()\n    plt.suptitle('Validation Loss and Accuracy') \n    plt.xlabel('Epoch')\n    plt.ylabel('Loss/Accuracy')\n    plt.plot(np.arange(0, n), val_loss, label = 'val_loss')\n    plt.plot(np.arange(0, n), val_accuracy, label = 'val_accuracy')\n    \n    plt.legend()\n    \n    plt.figure()\n    plt.title('Loss') \n    plt.xlabel('Epoch')\n    plt.ylabel('Loss')\n    plt.plot(np.arange(0, n), loss, label = 'train_loss')\n    plt.plot(np.arange(0, n), val_loss, label = 'val_loss')\n\n    plt.legend()\n    \n    plt.figure()\n    plt.title('Accuracy') \n    plt.xlabel('Epoch')\n    plt.ylabel('Accuracy')\n    plt.plot(np.arange(0, n), accuracy, label = 'train_accuracy')\n    plt.plot(np.arange(0, n), val_accuracy, label = 'val_accuracy')\n\n    plt.legend()\n\ntrain_top_model()","metadata":{"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# Based on the previous convolutional blocks output, redesign a fine-tune full-connected block by change weight slightly\ntop_model_weights_path = 'bottleneck_fc_model.h5'\n\nmodel = applications.VGG16(weights = None, include_top = False, input_shape = (img_width, img_height, 3))\n# model = applications.VGG16(weights = 'imagenet', include_top = False, input_shape = (img_width, img_height, 3))\n# model = applications.InceptionResNetV2(weights = 'imagenet', include_top = False, input_shape = (img_width, img_height, 3))\n# model = applications.InceptionResNetV2(weights = None, include_top = False, input_shape = (img_width, img_height, 3))\n\ntop_model = Sequential()\n\ntop_model.add(Flatten(input_shape = model.output_shape[1:]))\ntop_model.add(Dense(256, activation = 'relu'))\ntop_model.add(Dropout(0.5))\ntop_model.add(Dense(4, activation = 'softmax'))\n\ntop_model.load_weights(top_model_weights_path)\n\nmodel = Model(inputs = model.input, outputs = top_model(model.output))\n\n# Skip training of first 15 layers, which are all convolutional blocks\nfor layer in model.layers[:15]:\n    layer.trainable = False\n    \nfor layer in model.layers:\n    print(layer, layer.trainable)\n\n# Use new optimizer with slow learning rate\n\n# keras.optimizers.SGD(lr=0.01, momentum=0.0, decay=0.0, nesterov=False)\n# keras.optimizers.RMSprop(lr=0.001, rho=0.9, epsilon=None, decay=0.0)\n# keras.optimizers.Adagrad(lr=0.01, epsilon=None, decay=0.0)\n# keras.optimizers.Adadelta(lr=1.0, rho=0.95, epsilon=None, decay=0.0)\n# keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)\n# keras.optimizers.Adamax(lr=0.002, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0)\n# keras.optimizers.Nadam(lr=0.002, beta_1=0.9, beta_2=0.999, epsilon=None, schedule_decay=0.004)\nmodel.compile(\n    loss = 'categorical_crossentropy',\n    optimizer = keras.optimizers.RMSprop(lr = 0.00001, rho = 0.9),\n    # optimizer = keras.optimizers.SGD(lr = 1e-4, momentum = 0.9),\n    metrics = ['accuracy']\n)\n\ntrain_data_generator = ImageDataGenerator(\n    rescale = 1. / 255,\n    shear_range = 0.2,\n    zoom_range = 0.2,\n    horizontal_flip = True\n)\n\ntest_data_generator = ImageDataGenerator(\n    rescale = 1. / 255\n)\n\ntrain_generator = train_data_generator.flow_from_directory(\n    train_path,\n    target_size = (img_height, img_width),\n    batch_size = batch_size,\n    class_mode = 'categorical'\n)\n\ntest_generator = test_data_generator.flow_from_directory(\n    test_path,\n    target_size = (img_height, img_width),\n    batch_size = batch_size,\n    class_mode = 'categorical'\n)\n\nhistory_3 = model.fit_generator(\n    train_generator,\n    steps_per_epoch = train_size // batch_size,\n    epochs = epochs,\n    validation_data = test_generator,\n    validation_steps = test_size // batch_size\n)\n\n# Plot the accruacy, loss, train accuracy and train loss\nloss = history_3.history['loss']\nval_loss = history_3.history['val_loss']\naccuracy = history_3.history['accuracy']\nval_accuracy = history_3.history['val_accuracy']\n\nplt.style.use(\"ggplot\")\nn = epochs\n\nplt.figure()\nplt.suptitle('Train Loss and Accuracy') \nplt.xlabel('Epoch')\nplt.ylabel('Loss/Accuracy')\nplt.plot(np.arange(0, n), loss, label = 'train_loss')\nplt.plot(np.arange(0, n), accuracy, label = 'train_accuracy')\n\nplt.legend()\n\nplt.figure()\nplt.suptitle('Validation Loss and Accuracy') \nplt.xlabel('Epoch')\nplt.ylabel('Loss/Accuracy')\nplt.plot(np.arange(0, n), val_loss, label = 'val_loss')\nplt.plot(np.arange(0, n), val_accuracy, label = 'val_accuracy')\n\nplt.legend()\n\nplt.figure()\nplt.title('Loss') \nplt.xlabel('Epoch')\nplt.ylabel('Loss')\nplt.plot(np.arange(0, n), loss, label = 'train_loss')\nplt.plot(np.arange(0, n), val_loss, label = 'val_loss')\n\nplt.legend()\n\nplt.figure()\nplt.title('Accuracy') \nplt.xlabel('Epoch')\nplt.ylabel('Accuracy')\nplt.plot(np.arange(0, n), accuracy, label = 'train_accuracy')\nplt.plot(np.arange(0, n), val_accuracy, label = 'val_accuracy')\n\nplt.legend()","metadata":{"trusted":true},"execution_count":null,"outputs":[]}]}