{"id":124,"date":"2021-09-13T15:53:17","date_gmt":"2021-09-13T15:53:17","guid":{"rendered":"https:\/\/code-ml.com\/?p=124"},"modified":"2021-09-16T17:13:07","modified_gmt":"2021-09-16T17:13:07","slug":"how-to-create-a-custom-dataloader-for-an-image-dataset","status":"publish","type":"post","link":"https:\/\/codeml.ai\/index.php\/2021\/09\/13\/how-to-create-a-custom-dataloader-for-an-image-dataset\/","title":{"rendered":"How to create a custom PyTorch Dataset for an image dataset"},"content":{"rendered":"\n<p>With the advance in Deep learning, working with huge datasets has increasingly become part of the Data Science pipeline. Particularly in computer vision problems, we have a visual dataset that takes a huge amount of memory space to process and augment. Also, loading such a huge dataset takes a lot of time to process the dataset, and programs often slow down. To meet the requirement of processing a huge dataset we need an efficient way to process our dataset so that we have better memory and time management. <\/p>\n\n\n\n<p>The PyTorch framework provides a well-defined schema to process our dataset more efficiently so that we can use our GPU fully. It formalizes the data loading and preprocessing, which helps us process the data in real-time on multiple cores and can be fed to the deep learning model directly. This not only makes our code more efficient in terms of execution time and memory but also helps to make code more readable and manageable which is an absolute necessity for large projects.  <\/p>\n\n\n\n<p>In this article, we will learn how to code a custom Dataset class for a computer vision project using PyTorch&#8217;s <a href=\"https:\/\/pytorch.org\/docs\/stable\/data.html\" target=\"_blank\" rel=\"noreferrer noopener\">torch.utils.data.Dataset<\/a> class. Computer vision datasets can be organized in many different ways, we will work on three different types.<\/p>\n\n\n\n<ul><li>Images organised in class folders.<\/li><li>Images data organised as CSV file.<\/li><li>Images data organised in a folder with image name as class.<\/li><\/ul>\n\n\n\n<p>We will be using example cat and dog datasets to code custom datasets.<\/p>\n\n\n\n<h2>Images organised in class folders<\/h2>\n\n\n\n<div class=\"is-layout-flow wp-block-group\"><div class=\"wp-block-group__inner-container\">\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/code-ml.com\/wp-content\/uploads\/2021\/09\/undraw_Image__folder_re_hgp7.png\" alt=\"\" class=\"wp-image-3196\" width=\"321\" height=\"258\" srcset=\"https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Image__folder_re_hgp7.png 1005w, https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Image__folder_re_hgp7-300x241.png 300w, https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Image__folder_re_hgp7-768x617.png 768w\" sizes=\"(max-width: 321px) 100vw, 321px\" \/><figcaption>Ref<\/figcaption><\/figure><\/div>\n<\/div><\/div>\n\n\n\n<p>Before actually jumping into Dataloader, let&#8217;s first take a look at how our folder structure should be organized for this part. As you can below, the dataset is divided into class folders. <\/p>\n\n\n\n<div class=\"is-layout-flex wp-container-7 wp-block-columns\">\n<div class=\"is-layout-flow wp-block-column is-vertically-aligned-top\" style=\"flex-basis:100%\">\n<div class=\"is-layout-flow wp-block-group\"><div class=\"wp-block-group__inner-container\">\n<div class=\"is-layout-flex wp-container-4 wp-block-columns\">\n<div class=\"is-layout-flow wp-block-column\">\n<pre class=\"wp-block-code\"><code class=\"\">\u2500\u2500\u2500 train\n    \u251c\u2500\u2500 cat\n    \u2502    \u251c\u2500\u2500 cat1.png\n    \u2502    \u251c\u2500\u2500 cat2.png\n    \u2502    \u251c\u2500\u2500 ......\n    \u2502    \u2514\u2500\u2500 cat100.png\n    \u251c\u2500\u2500 dog\n            \u251c\u2500\u2500 dog1.png\n            \u251c\u2500\u2500 dog2.png\n            \u251c\u2500\u2500 ......\n            \u2514\u2500\u2500 dog100.png<\/code><\/pre>\n<\/div>\n\n\n\n<div class=\"is-layout-flow wp-block-column\">\n<pre class=\"wp-block-code\"><code class=\"\">\u2500\u2500\u2500 test\n    \u251c\u2500\u2500 cat\n    \u2502    \u251c\u2500\u2500 cat1.png\n    \u2502    \u251c\u2500\u2500 cat2.png\n    \u2502    \u251c\u2500\u2500 ......\n    \u2502    \u2514\u2500\u2500 cat10.png\n    \u251c\u2500\u2500 dog\n            \u251c\u2500\u2500 dog1.png\n            \u251c\u2500\u2500 dog2.png\n            \u251c\u2500\u2500 ......\n            \u2514\u2500\u2500 dog10.png<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div><\/div>\n<\/div>\n<\/div>\n\n\n\n<p>PyTorch provides two data primitives:&nbsp;<code><strong>torch.utils.data.DataLoader<\/strong><\/code>&nbsp;and&nbsp;<code><strong>torch.utils.data.Dataset<\/strong><\/code>&nbsp;that allow you to use pre-loaded datasets as well as your own data.&nbsp;<code>Dataset<\/code>&nbsp;stores the samples and their corresponding labels, and Data Loader wraps an iterable around the&nbsp;Dataset&nbsp;to enable easy access to the samples. Let us first write the code for custome Dataset Class and then we will explore each section:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">import os\nimport torch\nfrom PIL import Image\nfrom torchvision import transforms, datasets\n\nclass CustomDataset(torch.utils.data.Dataset):\n    def __init__(self, root_dir):\n        self.classnames=[&quot;cat&quot;, &quot;dog&quot;]   # Class List\n        self.root_dir = root_dir         # Train or Test\n        self.img_label_tuple = []        # Data list\n\n        # Loop to extract image path and label for folder name\n        for i in range(0, len(self.classnames)):\n            class_dir = os.path.join(root_dir, self.classnames[i])\n            all_files = [os.path.join(class_dir,f) for f in listdir(class_dir) if isfile(join(class_dir, f))]\n            for j in all_files:\n              item = tuple((j, i))\n              self.img_label_tuple.append(item)\n\n        # Simple transform\n        self.transform = transforms.Compose([transforms.Resize((32,32)),\n                                              transforms.ToTensor()])\n\n    def __len__(self):\n        # Returns lenght of the dataset.\n        return len(self.img_label_tuple)\n\n    # Contructur to process dataset, tranform it and returns (input image with label)\n    def __getitem__(self, idx):\n        path = self.img_label_tuple[idx][0]\n        class_id = self.classnames.index(img_label_tuple[idx][1])\n        img = Image.open(path).convert('RGB')\n        img = self.transform(img)\n    \n        return (img, class_id)<\/pre><\/div>\n\n\n\n<p>In the above code,  <strong>__init__()<\/strong> is known as a constructor which always gets executed when the object is called. In our CustomDataset, we initiate every Dataset with the class list, image_label_tuple list, and then we extract the dataset information from the given folder, In this way, we use the extracted data information to further process our image dataset. We have inherited the above custom class with the properties of torch.utils.data.Dataset, so that we can leverage features provided by this PyTorch&#8217;s class such as <em>multiprocessing<\/em>. <\/p>\n\n\n\n<p>We also defined two other constructor <strong>__len__() <\/strong>and <strong>__getitem__()<\/strong>, here <strong>__len__()<\/strong> is use to get the length of the given dataset. Whereas <strong>__getitem__()<\/strong> is a little complex, here we can define specific pre-processing techniques to pre-process our images before passing them to our machine learning model. <\/p>\n\n\n\n<p>Now that we have created the custom Dataset class for the dataset, we can move ahead with creating an iterable using <strong><a href=\"https:\/\/pytorch.org\/docs\/stable\/data.html\">torch.utils.data.DataLoader<\/a><\/strong>. In order to create the iterable we need our custom Dataset class and a few arguments given below, learn about more arguments <a href=\"https:\/\/pytorch.org\/docs\/stable\/data.html\">here<\/a>:<\/p>\n\n\n\n<ul><li><strong><span style=\"color: var(--theme-palette-color-1, #2872fa);\" class=\"ugb-highlight\">batch_size(int):<\/span><\/strong> Number of samples in each set of genearted batch.<\/li><li><strong><span style=\"color: var(--theme-palette-color-1, #2872fa);\" class=\"ugb-highlight\">shuffle(bool):<\/span><\/strong> If set True, the data will shuffle every time a batch is generated. Generally True for training.<\/li><li><strong><span style=\"color: var(--theme-palette-color-1, #2872fa);\" class=\"ugb-highlight\">num_worker:<\/span><\/strong> which denotes the number of processes that generate batches in parallel.<\/li><\/ul>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">bs = 64 \t#Batch Size\n\nroot_dir = &quot;Dataset folder path&quot;\ndataset = CustomDataset(root_dir)  # Dataset class initiation \ndataloader = torch.utils.data.DataLoader(dataset, bs, shuffle=True)<\/pre><\/div>\n\n\n\n<h2>Images data organised as CSV file<\/h2>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/code-ml.com\/wp-content\/uploads\/2021\/09\/undraw_Spreadsheet_re_cn18.png\" alt=\"\" class=\"wp-image-3209\" width=\"443\" height=\"306\" srcset=\"https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Spreadsheet_re_cn18.png 1006w, https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Spreadsheet_re_cn18-300x208.png 300w, https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Spreadsheet_re_cn18-768x532.png 768w\" sizes=\"(max-width: 443px) 100vw, 443px\" \/><\/figure><\/div>\n\n\n\n<p>In many Kaggle competitions, we are given we data folder and one CSV file. This file often contains meta-data of the dataset, for this section, we are assuming only two columns are given 1.) <strong>image_file_path<\/strong> 2.) <strong>class_label<\/strong>.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">import os\nimport torch\nimport pandas as pd\nfrom PIL import Image\nfrom torchvision import transforms, datasets\n\nclass CustomDataset(torch.utils.data.Dataset):\n    def __init__(self, root_dir):\n\n        self.dataframe = pd.read_csv(root_dir)   # Data frame from CSV file\n        self.class_list = self.dataframe['class_label'].unique()\n        # Simple transform\n        self.transform = transforms.Compose([transforms.Resize((32,32)),\n                                              transforms.ToTensor()])\n\n    def __len__(self):\n        # Returns lenght of the dataset.\n        return len(self.dataframe)\n\n    # Contructur to process dataset, tranform it and returns (input image with label)\n    def __getitem__(self, idx):\n        path = self.dataframe['img_path'].iloc[idx]\n        class_id = self.class_list.index(self.dataframe['class_label'].iloc[idx])\n        img = Image.open(path).convert('RGB')\n        img = self.transform(img)\n    \n        return (img, class_id)<\/pre><\/div>\n\n\n\n<p>Similar to first section, <strong>torch.utils.data.DataLoader<\/strong> will be use to create dataloaders, shown in the code given below:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">bs = 64 \t#Batch Size\n\nroot_dir = &quot;Dataset folder path&quot;\ndataset = CustomDataset(root_dir)  # Dataset class initiation \ndataloader = torch.utils.data.DataLoader(dataset, bs, shuffle=True)<\/pre><\/div>\n\n\n\n<h2>Images data organised in a folder with image name as class.<\/h2>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img decoding=\"async\" loading=\"lazy\" src=\"https:\/\/code-ml.com\/wp-content\/uploads\/2021\/09\/undraw_folder_files_nweq.png\" alt=\"\" class=\"wp-image-3211\" width=\"421\" height=\"318\" srcset=\"https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_folder_files_nweq.png 998w, https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_folder_files_nweq-300x227.png 300w, https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_folder_files_nweq-768x581.png 768w\" sizes=\"(max-width: 421px) 100vw, 421px\" \/><\/figure><\/div>\n\n\n\n<p>In a case when we have the image name as their classes we can just extract the class label from the image name. Below is the folder structure of such a scenario.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\">\u2500\u2500\u2500 train\n        \u251c\u2500\u2500 cat_1.png\n        \u251c\u2500\u2500 dog_2.png\n        \u251c\u2500\u2500 cat_3.png\n        \u251c\u2500\u2500 cat_4.png \n        \u251c\u2500\u2500 dog_5.png \n        \u251c\u2500\u2500 cat_6.png\n        \u251c\u2500\u2500 ......\n        \u2514\u2500\u2500 dog_100.png<\/code><\/pre>\n\n\n\n<p>Similar to the above approach we will be creating a CustomDataset for the above folder structure.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">import os\nimport torch\nimport pandas as pd\nfrom PIL import Image\nfrom torchvision import transforms, datasets\n\nclass CustomDataset(torch.utils.data.Dataset):\n    def __init__(self, root_dir):\n        self.classnames=[&quot;cat&quot;, &quot;dog&quot;]   # Class List\n        self.root_dir = root_dir         # Train or Test\n        self.img_path_list = []        # Data list\n\n        # Loop to extract image path\n        all_files = [os.path.join(self.root_dir,f) for f in listdir(self.root_dir) if isfile(join(self.root_dir, f))]\n        for item in all_files:\n          self.img_path_list.append(item)\n\n        # Simple transform\n        self.transform = transforms.Compose([transforms.Resize((32,32)),\n                                              transforms.ToTensor()])\n\n    def __len__(self):\n        # Returns lenght of the dataset.\n        return len(self.img_path_list)\n\n    # Contructur to process dataset, tranform it and returns (input image with label)\n    def __getitem__(self, idx):\n        path = self.img_path_list[idx]\n        class_id = self.classnames.index(path.split(&quot;_&quot;)[0])\n        img = Image.open(path).convert('RGB')\n        img = self.transform(img)\n    \n        return (img, class_id)<\/pre><\/div>\n\n\n\n<p>In <strong>__getitem__()<\/strong>, we simply extracted the class label name by splitting the pathname of the image. After creation of custom Dataset class. We are ready to create DataLoader again for the third time, <\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;python&quot;,&quot;mime&quot;:&quot;text\/x-python&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;Python&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;python&quot;}\">bs = 64 \t#Batch Size\n\nroot_dir = &quot;Dataset folder path&quot;\ndataset = CustomDataset(root_dir)  # Dataset class initiation \ndataloader = torch.utils.data.DataLoader(dataset, bs, shuffle=True)<\/pre><\/div>\n\n\n\n<h2>Conclution<\/h2>\n\n\n\n<p>In this article, we learned about Custom Dataset and DataLoader and how to create them in PyTorch. We also explored three different ways in which our data could be organized and how to create a Custom dataset for each set of scenarios. Hope you like the article and learned something, do share with one who needs such content. Read more articles <a href=\"https:\/\/code-ml.com\/index.php\/2021\/05\/22\/introduction-to-widgets-in-jupyter-notebook-build-your-own-pandas-profiler\/\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.  <\/p>\n\n\n\n<h5>References <\/h5>\n\n\n\n<ul><li><a href=\"https:\/\/pytorch.org\/docs\/stable\/data.html\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/pytorch.org\/docs\/stable\/data.html <\/a><\/li><li><a href=\"https:\/\/pytorch.org\/tutorials\/beginner\/basics\/data_tutorial.html\" target=\"_blank\" rel=\"noreferrer noopener\">https:\/\/pytorch.org\/tutorials\/beginner\/basics\/data_tutorial.html<\/a><\/li><\/ul>\n","protected":false},"excerpt":{"rendered":"<p>With the advance in Deep learning, working with huge datasets has increasingly become part of the Data Science pipeline. Particularly in computer vision problems, we have a visual dataset that takes a huge amount of memory space to process and augment. Also, loading such a huge dataset takes a lot of time to process the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3196,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[1],"tags":[24,25,23,22],"blocksy_meta":{"styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":6}},"aioseo_notices":[],"featured_image_urls":{"full":["https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Image__folder_re_hgp7.png",1005,807,false],"thumbnail":["https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Image__folder_re_hgp7-150x150.png",150,150,true],"medium":["https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Image__folder_re_hgp7-300x241.png",300,241,true],"medium_large":["https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Image__folder_re_hgp7-768x617.png",768,617,true],"large":["https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Image__folder_re_hgp7.png",1005,807,false],"1536x1536":["https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Image__folder_re_hgp7.png",1005,807,false],"2048x2048":["https:\/\/codeml.ai\/wp-content\/uploads\/2021\/09\/undraw_Image__folder_re_hgp7.png",1005,807,false]},"post_excerpt_stackable":"<p>With the advance in Deep learning, working with huge datasets has increasingly become part of the Data Science pipeline. Particularly in computer vision problems, we have a visual dataset that takes a huge amount of memory space to process and augment. Also, loading such a huge dataset takes a lot of time to process the dataset, and programs often slow down. To meet the requirement of processing a huge dataset we need an efficient way to process our dataset so that we have better memory and time management. The PyTorch framework provides a well-defined schema to process our dataset more&hellip;<\/p>\n","category_list":"<a href=\"https:\/\/codeml.ai\/index.php\/category\/how-to-code-ml\/\" rel=\"category tag\">How to. ?<\/a>","author_info":{"name":"Mohammad Ahmad","url":"https:\/\/codeml.ai\/index.php\/author\/md-ahmad0652\/"},"comments_num":"0 comments","_links":{"self":[{"href":"https:\/\/codeml.ai\/index.php\/wp-json\/wp\/v2\/posts\/124"}],"collection":[{"href":"https:\/\/codeml.ai\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codeml.ai\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codeml.ai\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codeml.ai\/index.php\/wp-json\/wp\/v2\/comments?post=124"}],"version-history":[{"count":16,"href":"https:\/\/codeml.ai\/index.php\/wp-json\/wp\/v2\/posts\/124\/revisions"}],"predecessor-version":[{"id":3224,"href":"https:\/\/codeml.ai\/index.php\/wp-json\/wp\/v2\/posts\/124\/revisions\/3224"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/codeml.ai\/index.php\/wp-json\/wp\/v2\/media\/3196"}],"wp:attachment":[{"href":"https:\/\/codeml.ai\/index.php\/wp-json\/wp\/v2\/media?parent=124"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codeml.ai\/index.php\/wp-json\/wp\/v2\/categories?post=124"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codeml.ai\/index.php\/wp-json\/wp\/v2\/tags?post=124"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}