{"id":5948,"date":"2023-06-14T08:02:11","date_gmt":"2023-06-14T16:02:11","guid":{"rendered":"https:\/\/live-cometml.pantheonsite.io\/?p=5948"},"modified":"2025-04-24T17:15:31","modified_gmt":"2025-04-24T17:15:31","slug":"building-a-neural-network-from-scratch-using-python-part-2","status":"publish","type":"post","link":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/","title":{"rendered":"Building a Neural Network From Scratch Using Python (Part 2)"},"content":{"rendered":"\n<link rel=\"\u201ccanonical\u201d\" href=\"\u201chttps:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\u201d\">\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"614\" src=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2023\/06\/1NUil-wyDtAKmoD-HjWXBLw-1024x614.webp\" alt=\"\" class=\"wp-image-5946\" srcset=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2023\/06\/1NUil-wyDtAKmoD-HjWXBLw-1024x614.webp 1024w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2023\/06\/1NUil-wyDtAKmoD-HjWXBLw-300x180.webp 300w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2023\/06\/1NUil-wyDtAKmoD-HjWXBLw-768x461.webp 768w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2023\/06\/1NUil-wyDtAKmoD-HjWXBLw-1536x922.webp 1536w, https:\/\/www.comet.com\/site\/wp-content\/uploads\/2023\/06\/1NUil-wyDtAKmoD-HjWXBLw.webp 1920w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"fh fi fj fk fl\">\n<div class=\"ab ca\">\n<div class=\"ch bg et eu ev ew\">\n<p id=\"8565\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">In the last post, you created a 2-layer neural network from scratch and now have a better understanding of how neural networks work.<\/p>\n<p id=\"f1b4\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">In this second part, you\u2019ll use your network to make predictions, and also compare its performance to two standard libraries (scikit-learn and Keras).<\/p>\n<p id=\"4b53\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">Specifically, you\u2019ll learn how to:<\/p>\n<ul class=\"\">\n<li id=\"d32d\" class=\"mv mw fo be b gm mx my mz gp na nb nc nq ne nf ng nr ni nj nk ns nm nn no np nt nu nv bj\" data-selectable-paragraph=\"\">Train and test the neural network<\/li>\n<li id=\"ad8b\" class=\"mv mw fo be b gm nw my mz gp nx nb nc nq ny nf ng nr nz nj nk ns oa nn no np nt nu nv bj\" data-selectable-paragraph=\"\">Build a 2-layer neural network using scikit-learn<\/li>\n<li id=\"a54f\" class=\"mv mw fo be b gm nw my mz gp nx nb nc nq ny nf ng nr nz nj nk ns oa nn no np nt nu nv bj\" data-selectable-paragraph=\"\">Build a 2-layer neural network using Keras<\/li>\n<\/ul>\n<p>\ud83d\udc49\ud83c\udffd Full code in Google Colab <a class=\"af mu\" href=\"https:\/\/colab.research.google.com\/drive\/14cDKLDqt24sWWM4fw_qnkIp6wVKlyMBG?usp=sharing\" target=\"_blank\" rel=\"noopener ugc nofollow\">here.<\/a><\/p>\n<h1 id=\"09ac\" class=\"ot ou fo be ov ow ox go oy oz pa gr pb pc pd pe pf pg ph pi pj pk pl pm pn po bj\" data-selectable-paragraph=\"\">Training and Testing the Neural Network<\/h1>\n<p id=\"a8f2\" class=\"pw-post-body-paragraph mv mw fo be b gm pp my mz gp pq nb nc nd pr nf ng nh ps nj nk nl pt nn no np fh bj\" data-selectable-paragraph=\"\">In case you\u2019ve forgotten what your network looks like, here\u2019s the code:<\/p>\n<pre>class NeuralNet():\n    '''\n    A two layer neural network\n    '''\n\n    def __init__(self, layers=[13,8,1], learning_rate=0.001, iterations=100):\n        self.params = {}\n        self.learning_rate = learning_rate\n        self.iterations = iterations\n        self.loss = []\n        self.sample_size = None\n        self.layers = layers\n        self.X = None\n        self.y = None\n\n    def init_weights(self):\n        '''\n        Initialize the weights from a random normal distribution\n        '''\n        np.random.seed(1) # Seed the random number generator\n        self.params[\"W1\"] = np.random.randn(self.layers[0], self.layers[1])\n        self.params['b1']  =np.random.randn(self.layers[1],)\n        self.params['W2'] = np.random.randn(self.layers[1],self.layers[2])\n        self.params['b2'] = np.random.randn(self.layers[2],)\n\n    def relu(self,Z):\n        '''\n        The ReLu activation function is to performs a threshold\n        operation to each input element where values less\n        than zero are set to zero.\n        '''\n        return np.maximum(0,Z)\n\n    def dRelu(self, x):\n        x[x&lt;=0] = 0\n        x[x&gt;0] = 1\n        return x\n\n    def eta(self, x):\n      ETA = 0.0000000001\n      return np.maximum(x, ETA)\n\n\n    def sigmoid(self,Z):\n        '''\n        The sigmoid function takes in real numbers in any range and\n        squashes it to a real-valued output between 0 and 1.\n        '''\n        return 1\/(1+np.exp(-Z))\n\n    def entropy_loss(self,y, yhat):\n        nsample = len(y)\n        yhat_inv = 1.0 - yhat\n        y_inv = 1.0 - y\n        yhat = self.eta(yhat) ## clips value to avoid NaNs in log\n        yhat_inv = self.eta(yhat_inv)\n        loss = -1\/nsample * (np.sum(np.multiply(np.log(yhat), y) + np.multiply((y_inv), np.log(yhat_inv))))\n        return loss\n\n    def forward_propagation(self):\n        '''\n        Performs the forward propagation\n        '''\n\n        Z1 = self.X.dot(self.params['W1']) + self.params['b1']\n        A1 = self.relu(Z1)\n        Z2 = A1.dot(self.params['W2']) + self.params['b2']\n        yhat = self.sigmoid(Z2)\n        loss = self.entropy_loss(self.y,yhat)\n\n        # save calculated parameters\n        self.params['Z1'] = Z1\n        self.params['Z2'] = Z2\n        self.params['A1'] = A1\n\n        return yhat,loss\n\n    def back_propagation(self,yhat):\n        '''\n        Computes the derivatives and update weights and bias according.\n        '''\n        y_inv = 1 - self.y\n        yhat_inv = 1 - yhat\n\n        dl_wrt_yhat = np.divide(y_inv, self.eta(yhat_inv)) - np.divide(self.y, self.eta(yhat))\n        dl_wrt_sig = yhat * (yhat_inv)\n        dl_wrt_z2 = dl_wrt_yhat * dl_wrt_sig\n\n        dl_wrt_A1 = dl_wrt_z2.dot(self.params['W2'].T)\n        dl_wrt_w2 = self.params['A1'].T.dot(dl_wrt_z2)\n        dl_wrt_b2 = np.sum(dl_wrt_z2, axis=0, keepdims=True)\n\n        dl_wrt_z1 = dl_wrt_A1 * self.dRelu(self.params['Z1'])\n        dl_wrt_w1 = self.X.T.dot(dl_wrt_z1)\n        dl_wrt_b1 = np.sum(dl_wrt_z1, axis=0, keepdims=True)\n\n        #update the weights and bias\n        self.params['W1'] = self.params['W1'] - self.learning_rate * dl_wrt_w1\n        self.params['W2'] = self.params['W2'] - self.learning_rate * dl_wrt_w2\n        self.params['b1'] = self.params['b1'] - self.learning_rate * dl_wrt_b1\n        self.params['b2'] = self.params['b2'] - self.learning_rate * dl_wrt_b2\n\n    def fit(self, X, y):\n        '''\n        Trains the neural network using the specified data and labels\n        '''\n        self.X = X\n        self.y = y\n        self.init_weights() #initialize weights and bias\n\n\n        for i in range(self.iterations):\n            yhat, loss = self.forward_propagation()\n            self.back_propagation(yhat)\n            self.loss.append(loss)\n\n    def predict(self, X):\n        '''\n        Predicts on a test data\n        '''\n        Z1 = X.dot(self.params['W1']) + self.params['b1']\n        A1 = self.relu(Z1)\n        Z2 = A1.dot(self.params['W2']) + self.params['b2']\n        pred = self.sigmoid(Z2)\n        return np.round(pred)\n\n    def acc(self, y, yhat):\n        '''\n        Calculates the accutacy between the predicted valuea and the truth labels\n        '''\n        acc = int(sum(y == yhat) \/ len(y) * 100)\n        return acc\n\n\n    def plot_loss(self):\n        '''\n        Plots the loss curve\n        '''\n        plt.plot(self.loss)\n        plt.xlabel(\"Iteration\")\n        plt.ylabel(\"logloss\")\n        plt.title(\"Loss curve for training\")\n        plt.show()<\/pre>\n<p id=\"d42d\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">To train and test the network, you\u2019ll read in the heart disease dataset, preprocess it like you would in any other machine learning task, specifically, you\u2019ll:<\/p>\n<ul class=\"\">\n<li id=\"4663\" class=\"mv mw fo be b gm mx my mz gp na nb nc nq ne nf ng nr ni nj nk ns nm nn no np nt nu nv bj\" data-selectable-paragraph=\"\">Split the data into train and test sets,<\/li>\n<li id=\"b7a6\" class=\"mv mw fo be b gm nw my mz gp nx nb nc nq ny nf ng nr nz nj nk ns oa nn no np nt nu nv bj\" data-selectable-paragraph=\"\">Standardize it using StandardScaler,<\/li>\n<li id=\"b6b5\" class=\"mv mw fo be b gm nw my mz gp nx nb nc nq ny nf ng nr nz nj nk ns oa nn no np nt nu nv bj\" data-selectable-paragraph=\"\">Initialize a model from your <code class=\"cw px py pz qa b\">NeuralNetwork<\/code> class, and finally,<\/li>\n<li id=\"a724\" class=\"mv mw fo be b gm nw my mz gp nx nb nc nq ny nf ng nr nz nj nk ns oa nn no np nt nu nv bj\" data-selectable-paragraph=\"\">Train and predict with the Model<\/li>\n<\/ul>\n<pre>import numpy as np\nimport warnings\nwarnings.filterwarnings(\"ignore\") #suppress warnings\nimport matplotlib.pyplot as plt\nfrom sklearn.model_selection import train_test_split\nfrom sklearn.preprocessing import StandardScaler\n\n#convert imput to numpy arrays\nX = heart_df.drop(columns=['heart_disease'])\n\n#replace target class with 0 and 1\n#1 means \"have heart disease\" and 0 means \"do not have heart disease\"\nheart_df['heart_disease'] = heart_df['heart_disease'].replace(1, 0)\nheart_df['heart_disease'] = heart_df['heart_disease'].replace(2, 1)\n\ny_label = heart_df['heart_disease'].values.reshape(X.shape[0], 1)\n\n#split data into train and test set\nXtrain, Xtest, ytrain, ytest = train_test_split(X, y_label, test_size=0.2, random_state=2)\n\n#standardize the dataset\nsc = StandardScaler()\nsc.fit(Xtrain)\nXtrain = sc.transform(Xtrain)\nXtest = sc.transform(Xtest)\n\nprint(f\"Shape of train set is {Xtrain.shape}\")\nprint(f\"Shape of test set is {Xtest.shape}\")\nprint(f\"Shape of train label is {ytrain.shape}\")\nprint(f\"Shape of test labels is {ytest.shape}\")<\/pre>\n<figure class=\"mg mh mi mj mk mf\"><\/figure>\n<figure class=\"mg mh mi mj mk mf mq mr paragraph-image\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg ml mm c\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:346\/0*oHD_uni106zhl3Si.png\" alt=\"\" width=\"346\" height=\"84\"><\/figure><div class=\"mq mr qb\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/0*oHD_uni106zhl3Si.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/0*oHD_uni106zhl3Si.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/0*oHD_uni106zhl3Si.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/0*oHD_uni106zhl3Si.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/0*oHD_uni106zhl3Si.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/0*oHD_uni106zhl3Si.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:692\/format:webp\/0*oHD_uni106zhl3Si.png 692w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 346px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/0*oHD_uni106zhl3Si.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/0*oHD_uni106zhl3Si.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/0*oHD_uni106zhl3Si.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/0*oHD_uni106zhl3Si.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/0*oHD_uni106zhl3Si.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/0*oHD_uni106zhl3Si.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:692\/0*oHD_uni106zhl3Si.png 692w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 346px\" data-testid=\"og\"><\/picture><\/div>\n<\/figure>\n<p id=\"d7f1\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">In the code block above, first, you get the training data, excluding the label\u2014this is done with the <code class=\"cw px py pz qa b\">drop<\/code> function. The <code class=\"cw px py pz qa b\">drop<\/code> function removes the specified column from the dataset and returns the remaining features. Next, you saved the label to a variable called<code class=\"cw px py pz qa b\">y_label<\/code>.<\/p>\n<p id=\"23e1\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">Next, you split the data into train and test set, with the test set taking 10 percent of the overall data. Then, you standardize the dataset. Standardization is important when working with neural networks, as it has a serious effect on the training time and network performance.<\/p>\n<p id=\"a89d\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">In the next code section, you\u2019ll initialize the neural network and train it using the fit function.<\/p>\n<pre>nn = NeuralNet() # create the NN model\nnn.fit(Xtrain, ytrain) #train the model<\/pre>\n<p id=\"f9f3\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">Here, you initialize the neural network with the default parameters:<\/p>\n<ul class=\"\">\n<li id=\"8065\" class=\"mv mw fo be b gm mx my mz gp na nb nc nq ne nf ng nr ni nj nk ns nm nn no np nt nu nv bj\" data-selectable-paragraph=\"\">layers ==&gt; [13,8,1]<\/li>\n<li id=\"46c2\" class=\"mv mw fo be b gm nw my mz gp nx nb nc nq ny nf ng nr nz nj nk ns oa nn no np nt nu nv bj\" data-selectable-paragraph=\"\">learning_rate ==&gt; 0.001<\/li>\n<li id=\"2c42\" class=\"mv mw fo be b gm nw my mz gp nx nb nc nq ny nf ng nr nz nj nk ns oa nn no np nt nu nv bj\" data-selectable-paragraph=\"\">iterations ==&gt; 100<\/li>\n<\/ul>\n<p id=\"1a0c\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">Then, you passed in the training data (<code class=\"cw px py pz qa b\">Xtrain<\/code>,<code class=\"cw px py pz qa b\">ytrain<\/code>) to the fit method. This is the training phase of the model.<\/p>\n<p id=\"ab4a\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">Now that you&#8217;re done training, let\u2019s plot the loss using the handy <code class=\"cw px py pz qa b\">plot_loss<\/code>function in the <code class=\"cw px py pz qa b\">NeuralNetwork<\/code> class:<\/p>\n<pre class=\"mg mh mi mj mk qc qa qd qe ax qf bj\"><span id=\"8428\" class=\"qg ou fo qa b ia qh qi l iq qj\" data-selectable-paragraph=\"\">nn.plot_loss()<\/span><\/pre>\n<figure class=\"mg mh mi mj mk mf mq mr paragraph-image\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg ml mm c\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:432\/1*eJQyOCpEDyQRna__cH4SfA.png\" alt=\"\" width=\"432\" height=\"288\"><\/figure><div class=\"mq mr qk\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*eJQyOCpEDyQRna__cH4SfA.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*eJQyOCpEDyQRna__cH4SfA.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*eJQyOCpEDyQRna__cH4SfA.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*eJQyOCpEDyQRna__cH4SfA.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*eJQyOCpEDyQRna__cH4SfA.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*eJQyOCpEDyQRna__cH4SfA.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:864\/format:webp\/1*eJQyOCpEDyQRna__cH4SfA.png 864w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 432px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*eJQyOCpEDyQRna__cH4SfA.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*eJQyOCpEDyQRna__cH4SfA.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*eJQyOCpEDyQRna__cH4SfA.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*eJQyOCpEDyQRna__cH4SfA.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*eJQyOCpEDyQRna__cH4SfA.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*eJQyOCpEDyQRna__cH4SfA.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:864\/1*eJQyOCpEDyQRna__cH4SfA.png 864w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 432px\" data-testid=\"og\"><\/picture><\/div>\n<\/figure>\n<p id=\"b067\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">You can see that the loss starts pretty high, then quickly goes down, and starts approaching zero. This gives you an insight into how the network learns. Now, let\u2019s try increasing the learning rate and the size of the hidden layer, and see how it affects the loss.<\/p>\n<pre>nn = NeuralNet(layers=[13,10,1], learning_rate=0.01, iterations=500) # create the NN model\nnn.fit(Xtrain, ytrain) #train the model\nnn.plot_loss()<\/pre>\n<figure class=\"mg mh mi mj mk mf mq mr paragraph-image\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg ml mm c\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:432\/1*iAo3OaiZwkIv-lEk-N3JdA.png\" alt=\"\" width=\"432\" height=\"288\"><\/figure><div class=\"mq mr qk\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*iAo3OaiZwkIv-lEk-N3JdA.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*iAo3OaiZwkIv-lEk-N3JdA.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*iAo3OaiZwkIv-lEk-N3JdA.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*iAo3OaiZwkIv-lEk-N3JdA.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*iAo3OaiZwkIv-lEk-N3JdA.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*iAo3OaiZwkIv-lEk-N3JdA.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:864\/format:webp\/1*iAo3OaiZwkIv-lEk-N3JdA.png 864w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 432px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*iAo3OaiZwkIv-lEk-N3JdA.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*iAo3OaiZwkIv-lEk-N3JdA.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*iAo3OaiZwkIv-lEk-N3JdA.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*iAo3OaiZwkIv-lEk-N3JdA.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*iAo3OaiZwkIv-lEk-N3JdA.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*iAo3OaiZwkIv-lEk-N3JdA.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:864\/1*iAo3OaiZwkIv-lEk-N3JdA.png 864w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 432px\" data-testid=\"og\"><\/picture><\/div>\n<\/figure>\n<p id=\"f632\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">You can clearly see that the loss is lower than the previous one. So these sets of parameters might actually be doing better than the first. To confirm this, let\u2019s show the accuracy on both the train and test set.<\/p>\n<p id=\"5b12\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">For the first Architecture, we have the following accuracies:<\/p>\n<pre>train_pred = nn.predict(Xtrain)\ntest_pred = nn.predict(Xtest)\n\nprint(\"Train accuracy is {}\".format(nn.acc(ytrain, train_pred)))\nprint(\"Test accuracy is {}\".format(nn.acc(ytest, test_pred)))<\/pre>\n<figure class=\"mg mh mi mj mk mf mq mr paragraph-image\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg ml mm c\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:314\/1*VRoIogc4eZx5fyM9UMWkFg.png\" alt=\"\" width=\"314\" height=\"57\"><\/figure><div class=\"mq mr ql\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*VRoIogc4eZx5fyM9UMWkFg.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*VRoIogc4eZx5fyM9UMWkFg.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*VRoIogc4eZx5fyM9UMWkFg.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*VRoIogc4eZx5fyM9UMWkFg.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*VRoIogc4eZx5fyM9UMWkFg.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*VRoIogc4eZx5fyM9UMWkFg.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:628\/format:webp\/1*VRoIogc4eZx5fyM9UMWkFg.png 628w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 314px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*VRoIogc4eZx5fyM9UMWkFg.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*VRoIogc4eZx5fyM9UMWkFg.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*VRoIogc4eZx5fyM9UMWkFg.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*VRoIogc4eZx5fyM9UMWkFg.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*VRoIogc4eZx5fyM9UMWkFg.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*VRoIogc4eZx5fyM9UMWkFg.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:628\/1*VRoIogc4eZx5fyM9UMWkFg.png 628w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 314px\" data-testid=\"og\"><\/picture><\/div>\n<\/figure>\n<p id=\"8908\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">For the second network, I had the same set of accuracies. This suggests that the second model is overfitting the data and the first model is actually better.<\/p>\n<p id=\"72a2\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">And just so you know, those are pretty great accuracies for a Neural Network you built from scratch!<\/p>\n<h1 id=\"fadb\" class=\"ot ou fo be ov ow ox go oy oz pa gr pb pc qm pe pf pg qn pi pj pk qo pm pn po bj\" data-selectable-paragraph=\"\">Working with Python Libraries<\/h1>\n<p id=\"a010\" class=\"pw-post-body-paragraph mv mw fo be b gm pp my mz gp pq nb nc nd pr nf ng nh ps nj nk nl pt nn no np fh bj\" data-selectable-paragraph=\"\">Just to spice it up, let\u2019s compare your implementation with standard libraries like <a class=\"af mu\" href=\"https:\/\/heartbeat.comet.ml\/introduction-to-deep-learning-with-keras-c7c3d14e1527\" target=\"_blank\" rel=\"noopener ugc nofollow\">Keras<\/a> and scikit-learn. If you don\u2019t have these libraries installed on your machine, you either have to install them or use <a class=\"af mu\" href=\"https:\/\/colab.research.google.com\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">Google Colab<\/a> for this section.<\/p>\n<h2 id=\"f7df\" class=\"qg ou fo be ov qp qq qr oy qs qt qu pb nd qv qw qx nh qy qz ra nl rb rc rd re bj\" data-selectable-paragraph=\"\">A 2-Layer Neural Network with scikit-learn<\/h2>\n<p id=\"acc9\" class=\"pw-post-body-paragraph mv mw fo be b gm pp my mz gp pq nb nc nd pr nf ng nh ps nj nk nl pt nn no np fh bj\" data-selectable-paragraph=\"\">The <a class=\"af mu\" href=\"https:\/\/scikit-learn.org\/stable\/modules\/generated\/sklearn.neural_network.MLPClassifier.html\" target=\"_blank\" rel=\"noopener ugc nofollow\">MLPClassifier<\/a> in the scikit-learn package contains an implementation of a neural network. To use it, first, you have to import it from the <code class=\"cw px py pz qa b\">sklearn.neural_network<\/code> class, and initialize the architecture:<\/p>\n<pre>from sklearn.neural_network import MLPClassifier\nfrom sklearn.metrics import accuracy_score\n\nsknet = MLPClassifier(hidden_layer_sizes=(8), learning_rate_init=0.001, max_iter=100)<\/pre>\n<p id=\"3b28\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">Notice that you specify just the number of hidden nodes when using the MLPClassifier\u2014this is because the size of the input feature is inferred from the dimension of the input data. Also, you can specify the learning rate and the number of iterations. To keep things fair, you\u2019ll use the same parameters you used for your own Neural Net. That is 8 hidden nodes, a learning rate of 0.001 and 100 iterations.<\/p>\n<p id=\"bc1e\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">Let\u2019s train this network and calculate its accuracy:<\/p>\n<pre>sknet.fit(Xtrain, ytrain)\npreds_train = sknet.predict(Xtrain)\npreds_test = sknet.predict(Xtest)\n\nprint(\"Train accuracy of sklearn neural network: {}\".format(round(accuracy_score(preds_train, ytrain),2)*100))\nprint(\"Test accuracy of sklearn neural network: {}\".format(round(accuracy_score(preds_test, ytest),2)*100))<\/pre>\n<figure class=\"mg mh mi mj mk mf mq mr paragraph-image\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg ml mm c\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:570\/1*N7jlT8BqDfXeYlvwii4P-A.png\" alt=\"\" width=\"570\" height=\"59\"><\/figure><div class=\"mq mr rf\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*N7jlT8BqDfXeYlvwii4P-A.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*N7jlT8BqDfXeYlvwii4P-A.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*N7jlT8BqDfXeYlvwii4P-A.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*N7jlT8BqDfXeYlvwii4P-A.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*N7jlT8BqDfXeYlvwii4P-A.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*N7jlT8BqDfXeYlvwii4P-A.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1140\/format:webp\/1*N7jlT8BqDfXeYlvwii4P-A.png 1140w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 570px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*N7jlT8BqDfXeYlvwii4P-A.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*N7jlT8BqDfXeYlvwii4P-A.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*N7jlT8BqDfXeYlvwii4P-A.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*N7jlT8BqDfXeYlvwii4P-A.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*N7jlT8BqDfXeYlvwii4P-A.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*N7jlT8BqDfXeYlvwii4P-A.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1140\/1*N7jlT8BqDfXeYlvwii4P-A.png 1140w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 570px\" data-testid=\"og\"><\/picture><\/div>\n<\/figure>\n<p id=\"6bce\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">Well, can you believe it! Your accuracy is actually higher than that of scikit-learn. This does not mean that you can use your Neural Network in production though. The catch here is that many standard implementations of neural networks use different optimization strategies regarding weight initialization, model training, gradient updates, adaptive learning rates, regularization, and so on, and these are important to consider when using models in industry.<\/p>\n<p id=\"f1a6\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">While we can implement most of these optimizations in our implementation, we\u2019ll refrain from doing that in this post. If interested, check out these amazing articles:<\/p>\n<div class=\"rg rh ri rj rk rl\">\n<ul>\n<li class=\"rm ab ik\"><a href=\"https:\/\/www.jeremyjordan.me\/nn-learning-rate\/\">Setting the learning rate of your neural network<\/a><\/li>\n<li class=\"rm ab ik\"><a href=\"https:\/\/machinelearningmastery.com\/gentle-introduction-mini-batch-gradient-descent-configure-batch-size\/\">A Gentle Introduction to Mini-Batch Gradient Descent and How to Configure Batch Size<\/a><\/li>\n<li class=\"rm ab ik\"><a href=\"https:\/\/www.geeksforgeeks.org\/ml-mini-batch-gradient-descent-with-python\/\">ML | Mini-Batch Gradient Descent with Python<\/a><\/li>\n<li class=\"rm ab ik\"><a href=\"https:\/\/towardsdatascience.com\/weight-initialization-techniques-in-neural-networks-26c649eb3b78\">Weight Initialization Techniques in Neural Networks<\/a><\/li>\n<li class=\"rm ab ik\"><a href=\"https:\/\/medium.com\/@pdquant\/all-the-backpropagation-derivatives-d5275f727f60\">All the Backpropagation derivatives<\/a><\/li>\n<\/ul>\n<\/div>\n<p>Next, let\u2019s see how to create a neural network with Keras.<\/p>\n<h2 id=\"2901\" class=\"qg ou fo be ov qp qq qr oy qs qt qu pb nd qv qw qx nh qy qz ra nl rb rc rd re bj\" data-selectable-paragraph=\"\">A 2-Layer Neural Network with Keras<\/h2>\n<p id=\"c575\" class=\"pw-post-body-paragraph mv mw fo be b gm pp my mz gp pq nb nc nd pr nf ng nh ps nj nk nl pt nn no np fh bj\" data-selectable-paragraph=\"\"><a class=\"af mu\" href=\"https:\/\/keras.io\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">Keras<\/a> is an open-source deep-learning library written in Python. It was designed to make experimentation with deep learning libraries faster and easier. In this article, you&#8217;ll be using the Tensorflow Implementation of Keras (tf.keras). This implementation is similar to normal Keras. The only difference is the way it is imported.<\/p>\n<p id=\"6d81\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">To create a neural network model in tf.keras, you have to import the Sequential, Layers and Dense modules. The <code class=\"cw px py pz qa b\">Sequential<\/code> module can accept a series of layers stacked on top of each other.<\/p>\n<p id=\"4cf5\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">Let\u2019s demonstrate this below:<\/p>\n<pre>from tensorflow.keras import Sequential\nfrom tensorflow.keras.layers import Dense\nfrom tensorflow.keras.optimizers import Adam\n\n# define the model\nmodel = Sequential()\nmodel.add(Dense(8, input_shape=(13,)))\nmodel.add(Dense(1, activation='sigmoid'))<\/pre>\n<p id=\"2824\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">In the code section above, you created a <code class=\"cw px py pz qa b\">Sequential<\/code> model. This tells Keras that you want to create stacks of layers. Next, you add two <code class=\"cw px py pz qa b\">Dense<\/code> layers. The first <code class=\"cw px py pz qa b\">Dense<\/code> layer has an input shape of 13 and 8 hidden nodes, while the second <code class=\"cw px py pz qa b\">Dense<\/code> layer, which is your output, has a single node and uses the sigmoid activation function.<\/p>\n<p id=\"b8ba\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">Next, compile the model by passing in the loss function, an optimizer that tells the network how to learn, and a metric to be calculated:<\/p>\n<pre># compile the model\nopt = Adam(learning_rate=0.001)\nmodel.compile(optimizer=opt, loss='binary_crossentropy', metrics=['accuracy'])<\/pre>\n<p id=\"40c2\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">There are many types of optimizers you can choose from, and each may affect the network\u2019s performance. Start with the Adam optimizer here, but feel free to try other ones <a class=\"af mu\" href=\"https:\/\/keras.io\/optimizers\/\" target=\"_blank\" rel=\"noopener ugc nofollow\">here<\/a>. Also, use a binary cross-entropy loss function, given that you&#8217;re working on a binary classification task.<\/p>\n<p id=\"ff13\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">After compiling, you\u2019ll train the network and evaluate it:<\/p>\n<pre>model.fit(Xtrain, ytrain, epochs=100, verbose=0)\ntrain_acc = model.evaluate(Xtrain, ytrain, verbose=0)[1]\ntest_acc = model.evaluate(Xtest, ytest, verbose=0)[1]\n\nprint(\"Train accuracy of keras neural network: {}\".format(round((train_acc * 100), 2)))\nprint(\"Test accuracy of keras neural network: {}\".format(round((test_acc * 100),2)))<\/pre>\n<figure class=\"mg mh mi mj mk mf mq mr paragraph-image\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg ml mm c\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:570\/1*aSRQJSHGesxHTndzAFnIBA.png\" alt=\"\" width=\"570\" height=\"56\"><\/figure><div class=\"mq mr rf\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*aSRQJSHGesxHTndzAFnIBA.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*aSRQJSHGesxHTndzAFnIBA.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*aSRQJSHGesxHTndzAFnIBA.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*aSRQJSHGesxHTndzAFnIBA.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*aSRQJSHGesxHTndzAFnIBA.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*aSRQJSHGesxHTndzAFnIBA.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1140\/format:webp\/1*aSRQJSHGesxHTndzAFnIBA.png 1140w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 570px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*aSRQJSHGesxHTndzAFnIBA.png 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*aSRQJSHGesxHTndzAFnIBA.png 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*aSRQJSHGesxHTndzAFnIBA.png 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*aSRQJSHGesxHTndzAFnIBA.png 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*aSRQJSHGesxHTndzAFnIBA.png 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*aSRQJSHGesxHTndzAFnIBA.png 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1140\/1*aSRQJSHGesxHTndzAFnIBA.png 1140w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 570px\" data-testid=\"og\"><\/picture><\/div>\n<\/figure>\n<p id=\"ea21\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">And that&#8217;s it! The accuracies of Keras on both the train and test sets are similar to what you have in your own Neural Network.<\/p>\n<h1 id=\"dc3d\" class=\"ot ou fo be ov ow ox go oy oz pa gr pb pc qm pe pf pg qn pi pj pk qo pm pn po bj\" data-selectable-paragraph=\"\">Summary<\/h1>\n<p id=\"a96e\" class=\"pw-post-body-paragraph mv mw fo be b gm pp my mz gp pq nb nc nd pr nf ng nh ps nj nk nl pt nn no np fh bj\" data-selectable-paragraph=\"\">That\u2019s it\u2026 You\u2019ve built, trained, and tested a neural network from scratch, and also compared the performance with 2 standard deep learning libraries.<\/p>\n<p id=\"74ad\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">In summary, to create a neural network from scratch, you have to perform the following:<\/p>\n<ol class=\"\">\n<li id=\"8056\" class=\"mv mw fo be b gm mx my mz gp na nb nc nq ne nf ng nr ni nj nk ns nm nn no np se nu nv bj\" data-selectable-paragraph=\"\">Get training data and target variable<\/li>\n<li id=\"9782\" class=\"mv mw fo be b gm nw my mz gp nx nb nc nq ny nf ng nr nz nj nk ns oa nn no np se nu nv bj\" data-selectable-paragraph=\"\">Initialize the weights and biases<\/li>\n<li id=\"a4ba\" class=\"mv mw fo be b gm nw my mz gp nx nb nc nq ny nf ng nr nz nj nk ns oa nn no np se nu nv bj\" data-selectable-paragraph=\"\">Compute forward propagation<\/li>\n<li id=\"8166\" class=\"mv mw fo be b gm nw my mz gp nx nb nc nq ny nf ng nr nz nj nk ns oa nn no np se nu nv bj\" data-selectable-paragraph=\"\">Compute backpropagation<\/li>\n<li id=\"67ce\" class=\"mv mw fo be b gm nw my mz gp nx nb nc nq ny nf ng nr nz nj nk ns oa nn no np se nu nv bj\" data-selectable-paragraph=\"\">Update weights and bias<\/li>\n<li id=\"d54b\" class=\"mv mw fo be b gm nw my mz gp nx nb nc nq ny nf ng nr nz nj nk ns oa nn no np se nu nv bj\" data-selectable-paragraph=\"\">Repeat steps 2-4 for n times<\/li>\n<\/ol>\n<h1 id=\"3228\" class=\"ot ou fo be ov ow ox go oy oz pa gr pb pc qm pe pf pg qn pi pj pk qo pm pn po bj\" data-selectable-paragraph=\"\">Conclusion<\/h1>\n<p id=\"a64a\" class=\"pw-post-body-paragraph mv mw fo be b gm pp my mz gp pq nb nc nd pr nf ng nh ps nj nk nl pt nn no np fh bj\" data-selectable-paragraph=\"\">I hope this has been an effective introduction to Neural Networks, AI and deep learning in general. More importantly, I hope you\u2019ve learned the steps and challenges in creating a Neural Network from scratch, using just Python and Numpy. While your network is not state-of-art, I\u2019m sure this post has helped you understand how neural network works.<\/p>\n<p id=\"a5a0\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">There are lots of other things that go into effectively optimizing a neural network for production. This is the reason why you won\u2019t need to use a \u201cbuilt-from-scratch\u201d Neural Network in the industry, instead, you\u2019ll use existing libraries that have been efficiently optimized.<\/p>\n<p id=\"82ba\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\">Congratulations, you\u2019re well on your way to becoming a great AI engineer. If you have any questions, suggestions, or feedback, don\u2019t hesitate to use the comment section below.<\/p>\n<figure class=\"mg mh mi mj mk mf mq mr paragraph-image\">\n<figure><img loading=\"lazy\" decoding=\"async\" class=\"bg ml mm c\" role=\"presentation\" src=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg\" alt=\"\" width=\"640\" height=\"345\"><\/figure><div class=\"mq mr sf\"><picture><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/format:webp\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/format:webp\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/format:webp\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/format:webp\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/format:webp\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/format:webp\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1280\/format:webp\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 1280w\" type=\"image\/webp\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 640px\"><source srcset=\"https:\/\/miro.medium.com\/v2\/resize:fit:640\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 640w, https:\/\/miro.medium.com\/v2\/resize:fit:720\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 720w, https:\/\/miro.medium.com\/v2\/resize:fit:750\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 750w, https:\/\/miro.medium.com\/v2\/resize:fit:786\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 786w, https:\/\/miro.medium.com\/v2\/resize:fit:828\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 828w, https:\/\/miro.medium.com\/v2\/resize:fit:1100\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 1100w, https:\/\/miro.medium.com\/v2\/resize:fit:1280\/1*FCiTcgvIHxdfEUurUWMsfQ.jpeg 1280w\" sizes=\"(min-resolution: 4dppx) and (max-width: 700px) 50vw, (-webkit-min-device-pixel-ratio: 4) and (max-width: 700px) 50vw, (min-resolution: 3dppx) and (max-width: 700px) 67vw, (-webkit-min-device-pixel-ratio: 3) and (max-width: 700px) 65vw, (min-resolution: 2.5dppx) and (max-width: 700px) 80vw, (-webkit-min-device-pixel-ratio: 2.5) and (max-width: 700px) 80vw, (min-resolution: 2dppx) and (max-width: 700px) 100vw, (-webkit-min-device-pixel-ratio: 2) and (max-width: 700px) 100vw, 640px\" data-testid=\"og\"><\/picture><\/div>\n<\/figure>\n<p id=\"d4bb\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\"><em class=\"sg\">Connect with me on <\/em><a class=\"af mu\" href=\"https:\/\/twitter.com\/risingodegua\" target=\"_blank\" rel=\"noopener ugc nofollow\"><strong class=\"be sh\"><em class=\"sg\">Twitter<\/em><\/strong><\/a><strong class=\"be sh\"><em class=\"sg\">.<\/em><\/strong><\/p>\n<p id=\"e600\" class=\"pw-post-body-paragraph mv mw fo be b gm mx my mz gp na nb nc nd ne nf ng nh ni nj nk nl nm nn no np fh bj\" data-selectable-paragraph=\"\"><em class=\"sg\">Connect with me on <\/em><a class=\"af mu\" href=\"https:\/\/www.linkedin.com\/in\/risingdeveloper\/\" target=\"_blank\" rel=\"noopener ugc nofollow\"><strong class=\"be sh\"><em class=\"sg\">LinkedIn<\/em><\/strong><\/a><strong class=\"be sh\"><em class=\"sg\">.<\/em><\/strong><\/p>\n<\/div>\n<\/div>\n<\/div>\n\n\n\n<div class=\"fh fi fj fk fl\">\n<div class=\"ab ca\">\n<div class=\"ch bg et eu ev ew\"><\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In the last post, you created a 2-layer neural network from scratch and now have a better understanding of how neural networks work. In this second part, you\u2019ll use your network to make predictions, and also compare its performance to two standard libraries (scikit-learn and Keras). Specifically, you\u2019ll learn how to: Train and test the [&hellip;]<\/p>\n","protected":false},"author":31,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"customer_name":"","customer_description":"","customer_industry":"","customer_technologies":"","customer_logo":"","footnotes":""},"categories":[6,7],"tags":[],"coauthors":[148],"class_list":["post-5948","post","type-post","status-publish","format-standard","hentry","category-machine-learning","category-tutorials"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.9 (Yoast SEO v25.9) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Building a Neural Network From Scratch Using Python (Part 2) - Comet<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Building a Neural Network From Scratch Using Python (Part 2)\" \/>\n<meta property=\"og:description\" content=\"In the last post, you created a 2-layer neural network from scratch and now have a better understanding of how neural networks work. In this second part, you\u2019ll use your network to make predictions, and also compare its performance to two standard libraries (scikit-learn and Keras). Specifically, you\u2019ll learn how to: Train and test the [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/\" \/>\n<meta property=\"og:site_name\" content=\"Comet\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/cometdotml\" \/>\n<meta property=\"article:published_time\" content=\"2023-06-14T16:02:11+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-04-24T17:15:31+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2023\/06\/1NUil-wyDtAKmoD-HjWXBLw-1024x614.webp\" \/>\n<meta name=\"author\" content=\"Rising Odegua\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@Cometml\" \/>\n<meta name=\"twitter:site\" content=\"@Cometml\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Rising Odegua\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Building a Neural Network From Scratch Using Python (Part 2) - Comet","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/","og_locale":"en_US","og_type":"article","og_title":"Building a Neural Network From Scratch Using Python (Part 2)","og_description":"In the last post, you created a 2-layer neural network from scratch and now have a better understanding of how neural networks work. In this second part, you\u2019ll use your network to make predictions, and also compare its performance to two standard libraries (scikit-learn and Keras). Specifically, you\u2019ll learn how to: Train and test the [&hellip;]","og_url":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/","og_site_name":"Comet","article_publisher":"https:\/\/www.facebook.com\/cometdotml","article_published_time":"2023-06-14T16:02:11+00:00","article_modified_time":"2025-04-24T17:15:31+00:00","og_image":[{"url":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2023\/06\/1NUil-wyDtAKmoD-HjWXBLw-1024x614.webp","type":"","width":"","height":""}],"author":"Rising Odegua","twitter_card":"summary_large_image","twitter_creator":"@Cometml","twitter_site":"@Cometml","twitter_misc":{"Written by":"Rising Odegua","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/#article","isPartOf":{"@id":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/"},"author":{"name":"Rising Odegua","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/1767de6937de72ff04ad93b3052052a8"},"headline":"Building a Neural Network From Scratch Using Python (Part 2)","datePublished":"2023-06-14T16:02:11+00:00","dateModified":"2025-04-24T17:15:31+00:00","mainEntityOfPage":{"@id":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/"},"wordCount":1243,"publisher":{"@id":"https:\/\/www.comet.com\/site\/#organization"},"image":{"@id":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2023\/06\/1NUil-wyDtAKmoD-HjWXBLw-1024x614.webp","articleSection":["Machine Learning","Tutorials"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/","url":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/","name":"Building a Neural Network From Scratch Using Python (Part 2) - Comet","isPartOf":{"@id":"https:\/\/www.comet.com\/site\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/#primaryimage"},"image":{"@id":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2023\/06\/1NUil-wyDtAKmoD-HjWXBLw-1024x614.webp","datePublished":"2023-06-14T16:02:11+00:00","dateModified":"2025-04-24T17:15:31+00:00","breadcrumb":{"@id":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/#primaryimage","url":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2023\/06\/1NUil-wyDtAKmoD-HjWXBLw-1024x614.webp","contentUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2023\/06\/1NUil-wyDtAKmoD-HjWXBLw-1024x614.webp"},{"@type":"BreadcrumbList","@id":"https:\/\/www.comet.com\/site\/blog\/building-a-neural-network-from-scratch-using-python-part-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.comet.com\/site\/"},{"@type":"ListItem","position":2,"name":"Building a Neural Network From Scratch Using Python (Part 2)"}]},{"@type":"WebSite","@id":"https:\/\/www.comet.com\/site\/#website","url":"https:\/\/www.comet.com\/site\/","name":"Comet","description":"Build Better Models Faster","publisher":{"@id":"https:\/\/www.comet.com\/site\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.comet.com\/site\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.comet.com\/site\/#organization","name":"Comet ML, Inc.","alternateName":"Comet","url":"https:\/\/www.comet.com\/site\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/#\/schema\/logo\/image\/","url":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2025\/01\/logo_comet_square.png","contentUrl":"https:\/\/www.comet.com\/site\/wp-content\/uploads\/2025\/01\/logo_comet_square.png","width":310,"height":310,"caption":"Comet ML, Inc."},"image":{"@id":"https:\/\/www.comet.com\/site\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/cometdotml","https:\/\/x.com\/Cometml","https:\/\/www.youtube.com\/channel\/UCmN63HKvfXSCS-UwVwmK8Hw"]},{"@type":"Person","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/1767de6937de72ff04ad93b3052052a8","name":"Rising Odegua","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.comet.com\/site\/#\/schema\/person\/image\/9fbdbbdb3b6eb0a0a854b1898b3e1544","url":"https:\/\/secure.gravatar.com\/avatar\/849e6783a937de45b52ff0d4237168a95de6942b2ebd3dd7457fb7ea09b93ad4?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/849e6783a937de45b52ff0d4237168a95de6942b2ebd3dd7457fb7ea09b93ad4?s=96&d=mm&r=g","caption":"Rising Odegua"},"url":"https:\/\/www.comet.com\/site\/blog\/author\/risingodegua\/"}]}},"_links":{"self":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/5948","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/users\/31"}],"replies":[{"embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/comments?post=5948"}],"version-history":[{"count":1,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/5948\/revisions"}],"predecessor-version":[{"id":15620,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/posts\/5948\/revisions\/15620"}],"wp:attachment":[{"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/media?parent=5948"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/categories?post=5948"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/tags?post=5948"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.comet.com\/site\/wp-json\/wp\/v2\/coauthors?post=5948"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}