{
  "source_file": "0930",
  "source_platform": "Hashnode",
  "author": "Fadhil Elrizanda",
  "title_listed": "Intel Images Classification Using VGG-19",
  "keywords": "",
  "domain": "图像处理",
  "content_type": "深度技术解析",
  "is_paid_flag": "否",
  "url": "https://elrizanda.hashnode.dev/intel-images-classification-using-vgg-19",
  "publish_date": "2024-12-08",
  "corpus_stage": "",
  "notes": "",
  "id": "3af59f5846fa",
  "collected_at": "2026-10-02T14:12:13",
  "title": "Intel Images Classification Using VGG-19",
  "body_markdown": "Intel Images Classification Using VGG-19\nPublished\nDecember 8, 2024\n•\n5\nmin read\n•\nView as Markdown\nF\nFadhil Elrizanda\nIntel image classification is a dataset consist of multiple scene. This dataset have 25,000 images with size 150 × 150 that are labeled for 6 difference categories like buildings, forest, glacier, mountain, sea, and street.\nThe dataset split into 14,000 images for training, 3,000 images for testing, and 7,000 images for prediction. In this article we will only use training and testing.\nlink :\nIntel Image Classification\nThis notebook running in kaggle, make sure to use GPU because VGG19 is computational exhausting. You can also use the notebook from here\nLink :\nnotebook\nBuilding VGG-19 From Scratch\nPreparing dependencies and dataset\n!pip install wandb\nWe will use wandb to monitor our model\nImport All Dependencies\nimport\ntensorflow\nas\ntf\nimport\nmatplotlib.pyplot\nas\nplt\nimport\nos\nimport\ndatetime\nfrom\nwandb.integration.keras\nimport\nWandbMetricsLogger\nimport\nwandb\nInitialize wandb\nwandb.login(key=\n\"key\"\n)\nYou can enter the key or manually input it when it is prompted. You need to make sure that your key is secret.\nData Preprocessing\nConfigure Parameters\nconfig = {\n\"BATCH_SIZE\"\n:\n64\n,\n\"IMG_SIZE\"\n:\n150\n,\n\"VAL_SPLIT\"\n:\n0.1\n,\n\"EPOCHS\"\n:\n10\n,\n\"PATIENCE\"\n:\n2\n}\nWe will create configuration variable to adjust our training pipeline. This configuration also uploaded to wandb for checking future model version\nLoad Dataset\nclass_names = os.listdir(\n\"/kaggle/input/intel-image-classification/seg_train/seg_train\"\n)\nprint(len(class_names))\n\ntrain_dataset = tf.keras.preprocessing.image_dataset_from_directory(\n\"/kaggle/input/intel-image-classification/seg_train/seg_train\"\n,\n    labels=\n\"inferred\"\n,\n    label_mode=\n\"categorical\"\n,\n    class_names=class_names,\n    color_mode=\n\"rgb\"\n,\n    batch_size=config[\n\"BATCH_SIZE\"\n],\n    image_size=(config[\n\"IMG_SIZE\"\n],config[\n\"IMG_SIZE\"\n]),\n    shuffle=\nTrue\n,\n    seed=\n32\n,\n    validation_split=config[\n\"VAL_SPLIT\"\n],\n    subset=\n\"training\"\n,\n    interpolation=\n\"bilinear\"\n,\n    verbose=\nTrue\n)\n\nvalid_dataset = tf.keras.preprocessing.image_dataset_from_directory(\n\"/kaggle/input/intel-image-classification/seg_train/seg_train\"\n,\n    labels=\n\"inferred\"\n,\n    label_mode=\n\"categorical\"\n,\n    class_names=class_names,\n    color_mode=\n\"rgb\"\n,\n    batch_size=config[\n\"BATCH_SIZE\"\n],\n    image_size=(config[\n\"IMG_SIZE\"\n],config[\n\"IMG_SIZE\"\n]),\n    shuffle=\nTrue\n,\n    seed=\n32\n,\n    validation_split=config[\n\"VAL_SPLIT\"\n],\n    subset=\n\"validation\"\n,\n    interpolation=\n\"bilinear\"\n,\n    verbose=\nTrue\n)\n\ntest_dataset = tf.keras.preprocessing.image_dataset_from_directory(\n\"/kaggle/input/intel-image-classification/seg_test/seg_test\"\n,\n    labels=\n'inferred'\n,\n    label_mode=\n'categorical'\n,\n    class_names=class_names,\n    color_mode=\n'rgb'\n,\n    batch_size=config[\n\"BATCH_SIZE\"\n],\n    image_size=(config[\n\"IMG_SIZE\"\n],config[\n\"IMG_SIZE\"\n]),\n    interpolation=\n'bilinear'\n,\n    verbose=\nTrue\n)\nIn this code we will create tf.data from directory. The label are one-hot encoded and the training and validation are splitted to 0.9 training and 0.1 validation. The image are resized to 150 × 150\nVisualize Distribution\ndef\nget_data_distribution\n(\ndataset=[]\n):\nlabels = []\nfor\ndata\nin\ndataset:\nfor\n_,label\nin\ndata:\n      labels.extend(tf.argmax(label,axis=\n1\n).numpy())\n  y, idx, count = tf.unique_with_counts(labels)\nreturn\ny, count\ndef\nvisualize_data\n(\nclass_data,count\n):\nplt.figure(figsize=(\n10\n,\n10\n))\n  plt.bar(class_data,count,align=\n\"center\"\n)\n  plt.tight_layout()\n  plt.title(\n\"Class Distribution\"\n)\n  plt.ylabel(\n\"Number of Data\"\n)\n  plt.xlabel(\n\"Class in number\"\n)\n  plt.show()\nclass_data, counts = get_data_distribution([train_dataset,valid_dataset,test_dataset])\nvisualize_data([class_names[cd]\nfor\ncd\nin\nclass_data],counts.numpy())\nWe will visualize the distribution of each labels, it is important to have balanced image class distribution to achieve better performance on each class.\nVisualize Sample Image\nplt.figure(figsize=(\n10\n,\n10\n))\nfor\nimg,label\nin\ntrain_dataset.take(\n1\n):\nfor\ni\nin\nrange(\n16\n):\n    ax = plt.subplot(\n4\n,\n4\n,i+\n1\n)\n    plt.imshow(img[i].numpy().astype(\n\"uint8\"\n))\n    plt.title(\nf\"Label :\n{class_names[tf.argmax(label[i])]}\n\"\n)\n    plt.axis(\nFalse\n)\nplt.tight_layout()\nplt.show()\nCode above will visualize 16 images from batch 1. We can see the data are not arranged or random. We can use it to train our model.\nBuilding and Training Model VGG-19\nclass\nVGG19\n(\ntf.keras.Model\n):\ndef\n__init__\n(\nself,input_shape,output_shape,**kwargs\n):\nsuper().__init__(**kwargs)\n    self.conv_blocks=[\n        self._conv_block(\n64\n,\n2\n),\n        self._conv_block(\n128\n,\n2\n),\n        self._conv_block(\n256\n,\n4\n),\n        self._conv_block(\n512\n,\n4\n),\n        self._conv_block(\n512\n,\n4\n),\n    ]\n    self.flatten = tf.keras.layers.Flatten()\n    self.dense1 = tf.keras.layers.Dense(units=\n4096\n,activation=\n\"relu\"\n,kernel_regularizer=tf.keras.regularizers.L2(\n0.0005\n))\n    self.dropout1 = tf.keras.layers.Dropout(\n0.5\n)\n    self.dense2 = tf.keras.layers.Dense(units=\n4096\n,activation=\n\"relu\"\n,kernel_regularizer=tf.keras.regularizers.L2(\n0.0005\n))\n    self.dropout2 = tf.keras.layers.Dropout(\n0.5\n)\n    self.output_layer = tf.keras.layers.Dense(units=output_shape,activation=\n\"softmax\"\n)\ndef\n_conv_block\n(\nself,filters,num_layers\n):\nblock = tf.keras.Sequential()\nfor\n_\nin\nrange(num_layers):\n      block.add(tf.keras.layers.Conv2D(filters=filters, kernel_size=(\n3\n,\n3\n), strides=(\n1\n,\n1\n), activation=\n\"relu\"\n,padding=\n\"same\"\n))\n    block.add(tf.keras.layers.MaxPool2D(pool_size=(\n2\n,\n2\n),strides=(\n2\n,\n2\n)))\nreturn\nblock\ndef\ncall\n(\nself,inputs,training=False\n):\nx = inputs\nfor\nblock\nin\nself.conv_blocks:\n      x = block(x)\n    x = self.flatten(x)\n    x = self.dense1(x)\n    x = self.dropout1(x,training=training)\n    x = self.dense2(x)\n    x= self.dropout2(x)\n    x = self.output_layer(x)\nreturn\nx\nFrom previous article we find out that the VGG model have different version based on how deep the network. The deepest version is VGG-19.\nWe construct the model from scratch using keras layers. In order to have flexibility, we build the model using class model. In this method we can repeat several blocks multiple times. This can be efficient especially building deeper and custom architecture.\nVGG_model = VGG19((config[\n\"IMG_SIZE\"\n],config[\n\"IMG_SIZE\"\n],\n3\n),len(class_names))\nVGG_model(tf.keras.layers.Input(shape=(config[\n\"IMG_SIZE\"\n],config[\n\"IMG_SIZE\"\n],\n3\n)))\nVGG_model.summary()\nAfter define the model, we build the model based on the configuration. From the model that we have been construct, the total parameters is 70,388,806 parameters. Which is very high number of parameters.\nVGG_model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=\n0.0001\n),\n                  loss=tf.keras.losses.CategoricalCrossentropy(),\n                  metrics=[\n\"accuracy\"\n])\nNext, we compile our model based on optimizer, loss, and defining our metric to accuracy.\nCustom Callback\nearly_stopping_cb = tf.keras.callbacks.EarlyStopping(patience=config[\n\"PATIENCE\"\n])\ncheckpoint_cb = tf.keras.callbacks.ModelCheckpoint(\n\"model_cb.keras\"\n,save_best_only=\nTrue\n)\n# Initialize wandb\nrun = wandb.init(\n    project=\n\"vgg19-intel-scratch\"\n,\n    config=config,\n)\nIn order to monitore our model we will use several callback like earlystopping, checkpoint, tensorboard, and wandb. After we define it we will initialize our wandb project and sync it with tensorboard.\nTraining Model\nhistory = VGG_model.fit(train_dataset,epochs=config[\n\"EPOCHS\"\n],validation_data=valid_dataset,callbacks=[early_stopping_cb,checkpoint_cb,\n                                          WandbMetricsLogger(log_freq=\n10\n)])\nTo train the model, we will call method fit with adjusted configuration. The history variable we use to get the history of the training process.\nOptionally you can use distributed learning if you have multiple GPU (check the notebook) to faster the training process\nEvaluation\nEvaluate on test dataset\nloss, acc = VGG_model.evaluate(test_data)\nprint(loss,acc)\nplt.plot(history.history[\n\"loss\"\n],label=\n\"Train loss\"\n)\nplt.plot(history.history[\n\"val_loss\"\n],label=\n\"Val loss\"\n)\nplt.xlabel(\n\"Epochs\"\n)\nplt.ylabel(\n\"Accuracy\"\n)\nplt.legend()\nplt.show()\nloss, acc = VGG_model.evaluate(test_data)\nprint(loss,acc)\nExport The Label From Test Dataset\nimport\nnumpy\nas\nnp\n\ny_pred = []  \ny_label = []\nfor\nimages, labels\nin\ntest_data:\n    batch_pred = tf.argmax(VGG_model(images, training=\nFalse\n), axis=\n1\n).numpy()\n# Get predictions\ny_pred.extend(batch_pred)  \n\n    batch_labels = tf.argmax(labels, axis=\n1\n).numpy()\n    y_label.extend(batch_labels)  \n\ny_pred = np.array(y_pred)\ny_label = np.array(y_label)\ntable = wandb.Table(columns=[\n\"Image\"\n,\n\"True Label\"\n,\n\"Predicted Label\"\n])\n\ny_pred = []  \ny_label = []  \nall_images = []\nfor\nimg_batch, labels\nin\ntest_data:\n    batch_pred = tf.argmax(VGG_model(img_batch, training=\nFalse\n), axis=\n1\n).numpy()\n    y_pred.extend(batch_pred)\n    batch_labels = tf.argmax(labels, axis=\n1\n).numpy()\n    y_label.extend(batch_labels)\n    all_images.extend(img_batch.numpy())\n\ny_pred = np.array(y_pred)\ny_label = np.array(y_label)\nall_images = np.array(all_images)\n\n\nplt.figure(figsize=(\n10\n,\n10\n))\nfor\ni\nin\nrange(\n16\n):  \n    ax = plt.subplot(\n4\n,\n4\n, i +\n1\n)\n    img = (all_images[i] *\n255\n).astype(\n\"uint8\"\n)  \n    plt.imshow(img)\n    plt.title(\nf\"Actual:\n{class_names[y_label[i]]}\n\\nPred:\n{class_names[y_pred[i]]}\n\"\n)\n    plt.axis(\nFalse\n)\n\nplt.tight_layout()\nplt.show()\nfor\ni\nin\nrange(\n16\n):\n    table.add_data(\n        wandb.Image(all_images[i]), \n        class_names[y_label[i]],     \n        class_names[y_pred[i]]      \n    )\n\nrun.log({\n\"predictions_table\"\n: table})\nrun.finish()\nEvaluate Using Confusion Matrix\nconfusion_matrix = tf.math.confusion_matrix(\n    y_label,\n    y_pred,\n    num_classes=len(class_names)\n)\nprint(\n\"Confusion Matrix:\"\n)\nprint(confusion_matrix.numpy())\nplt.figure()\nsns.heatmap(confusion_matrix.numpy(),annot=\nTrue\n,fmt=\n\"d\"\n,cmap=\n\"Blues\"\n)\nplt.xlabel(\n\"Predicted Label\"\n)\nplt.ylabel(\n\"Actual Label\"\n)\nplt.show()\nEvaluate using classification Report\nfrom\nsklearn.metrics\nimport\nclassification_report\nreport = classification_report(y_label,y_pred,target_names=[\nf\"Class\n{i}\n\"\nfor\ni\nin\nrange(len(class_names))])\nprint(\n\"Classification Report\"\n)\nprint(report)\nSummary\nFrom the article we know that building VGG 19 from scratch is feasible but it still need improvement. You also found that training VGG-19 is computational exhausting rather than previous model (LeNet). This model also have very number of parameter. We will explore more about how to build model that efficient with high accuracy\n#\ncomputer-vision\n#\nmachine-learning\n#\nartificial-intelligence\n#\ndeep-learning\n#\npython",
  "metadata": {
    "title": "Intel Images Classification Using VGG-19",
    "description": "Intel image classification is a dataset consist of multiple scene. This dataset have 25,000 images with size 150 × 150 that are labeled for 6 difference categories like buildings, forest, glacier, mountain, sea, and street.\nThe dataset split into 14,...",
    "keywords": null,
    "author": null,
    "og:title": "Intel Images Classification Using VGG-19",
    "og:description": "Intel image classification is a dataset consist of multiple scene. This dataset have 25,000 images with size 150 × 150 that are labeled for 6 difference categories like buildings, forest, glacier, mountain, sea, and street.\nThe dataset split into 14,...",
    "og:url": "https://elrizanda.hashnode.dev/intel-images-classification-using-vgg-19",
    "og:site_name": "elrizanda",
    "og:image": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733675294246/1acb6120-7666-4e9a-a46d-2687e5043c55.png",
    "og:image:width": "1200",
    "og:image:height": "630",
    "og:type": "article",
    "twitter:card": "summary_large_image",
    "twitter:title": "Intel Images Classification Using VGG-19",
    "twitter:description": "Intel image classification is a dataset consist of multiple scene. This dataset have 25,000 images with size 150 × 150 that are labeled for 6 difference categories like buildings, forest, glacier, mountain, sea, and street.\nThe dataset split into 14,...",
    "twitter:image": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733675294246/1acb6120-7666-4e9a-a46d-2687e5043c55.png",
    "article:published_time": "2024-12-08T16:29:22.881Z",
    "article:author": "https://elrizanda.hashnode.dev/@fadhilelrizanda"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/3af59f5846fa/code/body-000.txt",
      "chars": 19,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-001.txt",
      "chars": 150,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-002.txt",
      "chars": 23,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-003.txt",
      "chars": 110,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-004.txt",
      "chars": 1456,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-005.txt",
      "chars": 464,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-006.txt",
      "chars": 157,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-007.txt",
      "chars": 277,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-008.txt",
      "chars": 1397,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-009.txt",
      "chars": 180,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-010.txt",
      "chars": 182,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-011.txt",
      "chars": 265,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-012.txt",
      "chars": 212,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-013.txt",
      "chars": 58,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-014.txt",
      "chars": 176,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-015.txt",
      "chars": 58,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-016.txt",
      "chars": 356,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-017.txt",
      "chars": 989,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-018.txt",
      "chars": 164,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-019.txt",
      "chars": 151,
      "language": "text"
    },
    {
      "file": "attachments/3af59f5846fa/code/body-020.txt",
      "chars": 203,
      "language": "text"
    }
  ],
  "images": [
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733675294246/1acb6120-7666-4e9a-a46d-2687e5043c55.png",
      "bytes": 476141,
      "reused": true,
      "local_path": "attachments/3af59f5846fa/images/000.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733675294246/1acb6120-7666-4e9a-a46d-2687e5043c55.png",
      "alt": "Intel Images Classification Using VGG-19",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733399682882/9049256f-4d92-4cf4-a951-b4eadff6aae3.png",
      "bytes": 18594,
      "reused": true,
      "local_path": "attachments/3af59f5846fa/images/002.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733399682882/9049256f-4d92-4cf4-a951-b4eadff6aae3.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733400537449/d4837121-9806-4c29-a0b2-9e4dbd8f8422.png",
      "bytes": 1197453,
      "reused": true,
      "local_path": "attachments/3af59f5846fa/images/003.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733400537449/d4837121-9806-4c29-a0b2-9e4dbd8f8422.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733400905991/2d8cdad1-0718-45f8-8094-4a382d42b318.png",
      "bytes": 49524,
      "reused": true,
      "local_path": "attachments/3af59f5846fa/images/004.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733400905991/2d8cdad1-0718-45f8-8094-4a382d42b318.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674174467/899e9864-22a7-4304-a8e2-0d2f0b207b5a.png",
      "bytes": 21451,
      "reused": true,
      "local_path": "attachments/3af59f5846fa/images/005.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674174467/899e9864-22a7-4304-a8e2-0d2f0b207b5a.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674210488/9b3d1dcd-e86f-4291-b58a-4183820c73e5.png",
      "bytes": 18138,
      "reused": true,
      "local_path": "attachments/3af59f5846fa/images/006.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674210488/9b3d1dcd-e86f-4291-b58a-4183820c73e5.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674249505/4dfedb0e-6353-4dd2-9cda-7c9bd44266b1.png",
      "bytes": 6077,
      "reused": true,
      "local_path": "attachments/3af59f5846fa/images/007.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674249505/4dfedb0e-6353-4dd2-9cda-7c9bd44266b1.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674399328/1a934fcf-9b02-4793-b9a5-71cca2dd36f4.png",
      "bytes": 517345,
      "reused": true,
      "local_path": "attachments/3af59f5846fa/images/008.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674399328/1a934fcf-9b02-4793-b9a5-71cca2dd36f4.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674435420/21e6d207-f9e6-4ab5-a7fe-d1c709f359ff.png",
      "bytes": 6143,
      "reused": true,
      "local_path": "attachments/3af59f5846fa/images/009.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674435420/21e6d207-f9e6-4ab5-a7fe-d1c709f359ff.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674467901/c456484e-0667-4e84-b225-b3dc027751e4.png",
      "bytes": 21422,
      "reused": true,
      "local_path": "attachments/3af59f5846fa/images/010.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674467901/c456484e-0667-4e84-b225-b3dc027751e4.png",
      "alt": "",
      "downloaded": true
    },
    {
      "status": "ok",
      "url": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674496104/f317ce68-0050-4aef-8bfe-44f0a50aea14.png",
      "bytes": 13146,
      "reused": true,
      "local_path": "attachments/3af59f5846fa/images/011.png",
      "src": "https://cdn.hashnode.com/res/hashnode/image/upload/v1733674496104/f317ce68-0050-4aef-8bfe-44f0a50aea14.png",
      "alt": "",
      "downloaded": true
    }
  ],
  "audio": [],
  "videos": [],
  "links": [
    {
      "href": "https://elrizanda.hashnode.dev/intel-images-classification-using-vgg-19.md",
      "label": "View as Markdown",
      "type": "a"
    },
    {
      "href": "https://hashnode.com/@fadhilelrizanda",
      "label": "F",
      "type": "a"
    },
    {
      "href": "https://www.linkedin.com/in/fadhil-elrizanda/",
      "label": "",
      "type": "a"
    },
    {
      "href": "https://www.kaggle.com/datasets/puneet6060/intel-image-classification/data",
      "label": "Intel Image Classification",
      "type": "a"
    },
    {
      "href": "https://github.com/fadhilelrizanda/intel-scene-vgg19-scratch",
      "label": "notebook",
      "type": "a"
    },
    {
      "href": "https://elrizanda.hashnode.dev/tag/computer-vision",
      "label": "# computer-vision",
      "type": "a"
    },
    {
      "href": "https://elrizanda.hashnode.dev/tag/machine-learning",
      "label": "# machine-learning",
      "type": "a"
    },
    {
      "href": "https://elrizanda.hashnode.dev/tag/artificial-intelligence",
      "label": "# artificial-intelligence",
      "type": "a"
    },
    {
      "href": "https://elrizanda.hashnode.dev/tag/deep-learning",
      "label": "# deep-learning",
      "type": "a"
    },
    {
      "href": "https://elrizanda.hashnode.dev/tag/python",
      "label": "# python",
      "type": "a"
    }
  ],
  "retry_at": "2026-10-03T08:09:50",
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:51:00Z",
  "source_url": "https://elrizanda.hashnode.dev/intel-images-classification-using-vgg-19",
  "papers": [],
  "actual_video_files": [],
  "body_chars": 10702,
  "expected_body_images": 11,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/3af59f5846fa/pages/source.html",
  "local_html": "attachments/3af59f5846fa/pages/article.html",
  "body_base_path": "attachments/3af59f5846fa/pages/",
  "body_markdown_path": "attachments/3af59f5846fa/pages/article.md"
}