<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Petros Demetrakopoulos</title>
    <description>The latest articles on DEV Community by Petros Demetrakopoulos (@demetrakopetros).</description>
    <link>https://dev.to/demetrakopetros</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F36805%2Faf2e939b-ec6a-40c2-86bc-28d4ed138989.JPG</url>
      <title>DEV Community: Petros Demetrakopoulos</title>
      <link>https://dev.to/demetrakopetros</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/demetrakopetros"/>
    <language>en</language>
    <item>
      <title>EthairBalloons is now available for Python!</title>
      <dc:creator>Petros Demetrakopoulos</dc:creator>
      <pubDate>Wed, 06 Jul 2022 13:12:55 +0000</pubDate>
      <link>https://dev.to/demetrakopetros/ethairballoons-is-now-available-for-python-4gkf</link>
      <guid>https://dev.to/demetrakopetros/ethairballoons-is-now-available-for-python-4gkf</guid>
      <description>&lt;p&gt;Yes! &lt;br&gt;
It is finally there.&lt;br&gt;
The much-loved ORM library for the Ethereum Blockchain is now available for Python.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is EthAir Balloons ?
&lt;/h2&gt;

&lt;p&gt;EthAir Balloons is a strictly typed ORM library for Ethereum blockchain. It allows you to use Ethereum blockchain as a persistent storage in an organized and model-oriented way without writing custom complex Smart contracts.&lt;/p&gt;

&lt;p&gt;Until now, EthairBalloons was only &lt;a href="https://github.com/petrosDemetrakopoulos/ethairballoons"&gt;available for JavaScript&lt;/a&gt; and you could install it via npm (&lt;code&gt;npm install --save ethairballoons&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;However, from now on there is an official Python version too.&lt;br&gt;
you can check it out on this &lt;a href="https://github.com/petrosDemetrakopoulos/ethairballoons.py"&gt;GitHub repository&lt;/a&gt; and install it via &lt;code&gt;pip install ethairballoons&lt;/code&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/petrosDemetrakopoulos"&gt;
        petrosDemetrakopoulos
      &lt;/a&gt; / &lt;a href="https://github.com/petrosDemetrakopoulos/ethairballoons.py"&gt;
        ethairballoons.py
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A strictly typed ORM library for Ethereum blockchain. 
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
EthAir Balloons&lt;/h1&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://raw.githubusercontent.com/petrosDemetrakopoulos/ethairballoons/master/logo_official.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q8SrLhgX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/petrosDemetrakopoulos/ethairballoons/master/logo_official.png" width="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A strictly typed ORM library for Ethereum blockchain
It allows you to use Ethereum blockchain as a persistent storage in an organized and model-oriented way &lt;strong&gt;without writing custom complex Smart contracts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note
As transaction fees may be huge, it is strongly advised to only deploy EthAir Balloons models in private Ethereum blockchains or locally using
&lt;code&gt;ganache&lt;/code&gt;
&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
Installation&lt;/h1&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;pip install ethairballoons
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h1&gt;
Setup&lt;/h1&gt;
&lt;div class="highlight highlight-source-python notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s1"&gt;ethairballoons&lt;/span&gt; &lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-s1"&gt;ethairBalloons&lt;/span&gt;
&lt;span class="pl-c"&gt;# frist parameter is the IP of the Ethereum network we want to store data&lt;/span&gt;
&lt;span class="pl-c"&gt;# seconda parameter is the path to save to smart contract&lt;/span&gt;
&lt;span class="pl-s1"&gt;provider&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-en"&gt;ethairBalloons&lt;/span&gt;(&lt;span class="pl-s"&gt;'127.0.0.1'&lt;/span&gt;, &lt;span class="pl-s"&gt;'../'&lt;/span&gt;)

&lt;span class="pl-s1"&gt;mySchema&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-s1"&gt;provider&lt;/span&gt;.&lt;span class="pl-en"&gt;createSchema&lt;/span&gt;(&lt;span class="pl-s1"&gt;modelDefinition&lt;/span&gt;&lt;span class="pl-c1"&gt;=&lt;/span&gt;{
    &lt;span class="pl-s"&gt;'name'&lt;/span&gt;: &lt;span class="pl-s"&gt;"Car"&lt;/span&gt;,
    &lt;span class="pl-s"&gt;'contractName'&lt;/span&gt;: &lt;span class="pl-s"&gt;"carsContract"&lt;/span&gt;,
    &lt;span class="pl-s"&gt;'properties'&lt;/span&gt;: [{
            &lt;span class="pl-s"&gt;'name'&lt;/span&gt;: &lt;span class="pl-s"&gt;"model"&lt;/span&gt;,
            &lt;span class="pl-s"&gt;'type'&lt;/span&gt;: &lt;span class="pl-s"&gt;"bytes32"&lt;/span&gt;,
            &lt;span class="pl-s"&gt;'primaryKey'&lt;/span&gt;: &lt;span class="pl-c1"&gt;True&lt;/span&gt;
    },
        {
            &lt;span class="pl-s"&gt;'name'&lt;/span&gt;: &lt;span class="pl-s"&gt;"engine"&lt;/span&gt;,
            &lt;span class="pl-s"&gt;'type'&lt;/span&gt;: &lt;span class="pl-s"&gt;"bytes32"&lt;/span&gt;,
    },
        {
            &lt;span class="pl-s"&gt;'name'&lt;/span&gt;: &lt;span class="pl-s"&gt;"cylinders"&lt;/span&gt;,
            &lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/petrosDemetrakopoulos/ethairballoons.py"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;.&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>web3</category>
      <category>blockchain</category>
      <category>python</category>
    </item>
    <item>
      <title>Quick Tip: Reversing a string in Python</title>
      <dc:creator>Petros Demetrakopoulos</dc:creator>
      <pubDate>Wed, 06 Jan 2021 23:04:26 +0000</pubDate>
      <link>https://dev.to/demetrakopetros/quick-tip-reversing-a-string-in-python-b4g</link>
      <guid>https://dev.to/demetrakopetros/quick-tip-reversing-a-string-in-python-b4g</guid>
      <description>&lt;p&gt;You can easily reverse a string in python like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello"&lt;/span&gt;&lt;span class="p"&gt;[::&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This syntax reverses the string by converting it to an array (in python strings are actually arrays of characters) and then slicing it The syntax for the array slicing is as follows: &lt;code&gt;[start:end:step]&lt;/code&gt; where empty start means 0 and empty stop means the length of the array. So [::-1] means to slice the array from the 1st element to the last element in reverse order.&lt;/p&gt;

</description>
      <category>python</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Face mask detection with Tensorflow CNNs</title>
      <dc:creator>Petros Demetrakopoulos</dc:creator>
      <pubDate>Mon, 13 Jul 2020 14:49:18 +0000</pubDate>
      <link>https://dev.to/demetrakopetros/face-mask-detection-with-tensorflow-cnns-11io</link>
      <guid>https://dev.to/demetrakopetros/face-mask-detection-with-tensorflow-cnns-11io</guid>
      <description>

&lt;p&gt;COVID-19 has been an inspiration for many software and data engineers during the last months.&lt;br&gt;
This project demonstrates how a Convolutional Neural Network (CNN) can detect if a person in a picture is wearing a face mask or not.&lt;br&gt;
As you can easily understand the applications of this method may be very helpful for the prevention and the control of COVID-19 as it could be used in public places like airports, shopping malls etc.&lt;/p&gt;
&lt;h2&gt;
  
  
  Defining the problem
&lt;/h2&gt;

&lt;p&gt;Detecting if an image contains a person wearing a mask or not is a simple &lt;strong&gt;classification problem&lt;/strong&gt;.&lt;br&gt;
We have to classify the images between &lt;strong&gt;2 discrete classes&lt;/strong&gt;: The ones that contain a face mask and the ones that do not.&lt;/p&gt;
&lt;h2&gt;
  
  
  The dataset
&lt;/h2&gt;

&lt;p&gt;Hopefully, I found a dataset containing faces with and without masks online. It is available on this &lt;a href="https://github.com/prajnasb/observations/tree/master/experiements/data"&gt;github link&lt;/a&gt;.&lt;br&gt;
It contains 1,376 images. 690 images show people with face masks and 686 images show people without face masks.&lt;/p&gt;
&lt;h2&gt;
  
  
  Image classification and CNNs
&lt;/h2&gt;

&lt;p&gt;A bit of theoretical background first.&lt;br&gt;
Convolutional Neural Networks (CNN) are neural networks most commonly used to analyze images.&lt;br&gt;
A CNN receives an image as an input in the form of a 3D matrix. The first two dimensions corresponds to the width and height of the image in pixels while the third one corresponds to the RGB values of each pixel. &lt;/p&gt;

&lt;p&gt;CNNs consist of the following sequential modules (each one may contain more than one layer)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Convolution&lt;/li&gt;
&lt;li&gt;ReLu activation function&lt;/li&gt;
&lt;li&gt;Pooling&lt;/li&gt;
&lt;li&gt;Fully connected layers&lt;/li&gt;
&lt;li&gt;Output layer&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Convolution
&lt;/h3&gt;

&lt;p&gt;Convolution operation is an element-wise matrix multiplication operation.&lt;br&gt;
Convolutional layers take the three-dimensional input matrix we mentioned before and they pass a &lt;strong&gt;filter&lt;/strong&gt; (also known as convolutional kernel) over the image, applying it to a small window of pixels at a time (i.e 3x3 pixels) and moving this window until the entire image has been scanned. The convolutional operation calculates the dot product of the pixel values in the current filter window along with the weights defined in the filter. The output of this operation is the final convoluted image.&lt;/p&gt;

&lt;p&gt;The following animation (found in &lt;a href="https://developers.google.com/machine-learning/practica/image-classification/convolutional-neural-networks"&gt;Google developers portal&lt;/a&gt;) shows how the sliding o the window is performed over an image&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---DGfZ7F4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://developers.google.com/machine-learning/practica/image-classification/images/convolution_overview.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---DGfZ7F4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://developers.google.com/machine-learning/practica/image-classification/images/convolution_overview.gif" alt="Window sliding" width="880" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The core of image classification CNNs is that as the model trains what it really does is that &lt;strong&gt;it learns the values for the filter matrices that enable it to extract important features&lt;/strong&gt; (shapes, textures, colored areas, etc) in the image. Each convolutional layer applies one new filter to the convoluted image of the previous layer that can extract one more feature. So, as we stack more filters, the more features the CNN can extract from an image. &lt;/p&gt;
&lt;h3&gt;
  
  
  ReLu activation function
&lt;/h3&gt;

&lt;p&gt;After each convolution operation, CNN applies to the output a &lt;strong&gt;Rectified Linear Unit&lt;/strong&gt; (ReLu) function to the convolved image. &lt;br&gt;
As you may remember from the Machine Learning 101 course in university, ReLu is very commonly used in machine learning applications because it introduces nonlinearity into the model. This helps our model to &lt;strong&gt;generalize better&lt;/strong&gt; and avoid overfitting.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pooling
&lt;/h3&gt;

&lt;p&gt;Pooling is the process where the CNN downsamples the convolved image by reducing the number of dimensions of the feature map.&lt;br&gt;
It does so to reduce processing time and the computing power needed.&lt;br&gt;
During this process, it preserves the most important feature information. There are several methods that can be used for pooling. The most common ones are &lt;strong&gt;Max pooling&lt;/strong&gt; and &lt;strong&gt;Average pooling&lt;/strong&gt;.&lt;br&gt;
In our application, we will use max pooling as it is the most effective most of the times.&lt;br&gt;
Max pooling is very similar to the convolution process. A windows slides over the feature map and extracts tiles of a specified size. For each tile, max pooling picks the maximum value and adds it to a new feature map.&lt;/p&gt;

&lt;p&gt;The following animation (found in &lt;a href="https://developers.google.com/machine-learning/practica/image-classification/convolutional-neural-networks"&gt;Google developers portal&lt;/a&gt;) shows how max pooling operation is performed.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d2BTXISO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://developers.google.com/machine-learning/practica/image-classification/images/maxpool_animation.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d2BTXISO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://developers.google.com/machine-learning/practica/image-classification/images/maxpool_animation.gif" alt="Max Pooling" width="728" height="324"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Fully connected layers
&lt;/h3&gt;

&lt;p&gt;After pooling, there is always one or more fully connected layers. These layers perform the classification based on the features extracted from the image by the previously mentioned convolution processes. The last fully connected layer is the output layer which applies a softmax function to the output of the previous fully connected layer and returns a probability for each class.&lt;/p&gt;

&lt;p&gt;The general form of an image classification CNN is the one shown below:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kZOJUhAv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f3qp9loy9io16d3x5sjm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kZOJUhAv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/f3qp9loy9io16d3x5sjm.png" alt="image classification CNN" width="880" height="473"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Face mask detection
&lt;/h2&gt;

&lt;p&gt;I used Tensorflow and Keras to create the CNN that classifies the images as with or without mask.&lt;/p&gt;

&lt;p&gt;First, we need to randomly split the dataset in separate train / test sets.&lt;br&gt;
We do so with the following function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;train_test_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;trainPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;testPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;split_size&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;crnImage&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;'/'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;crnImage&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getsize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crnImage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;train_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;split_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;test_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;train_len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;shuffled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;train&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;train_len&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;train_len&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"train images with mask:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test images without mask:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

  &lt;span class="c1"&gt;#copying train and test images in seaparate directories
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;trainDataPoint&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
        &lt;span class="n"&gt;crnTrainDataPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;'/'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;trainDataPoint&lt;/span&gt;
        &lt;span class="n"&gt;newTrainDataPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="n"&gt;trainPath&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;'/'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;trainDataPoint&lt;/span&gt;
        &lt;span class="n"&gt;copyfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crnTrainDataPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newTrainDataPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;testDataPoint&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;crnTestDataPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;'/'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;testDataPoint&lt;/span&gt;
        &lt;span class="n"&gt;newTestDataPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="n"&gt;testPath&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;'/'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;testDataPoint&lt;/span&gt;
        &lt;span class="n"&gt;copyfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;crnTestDataPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newTestDataPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We then call it twice (one for the images that contain a mask and one fot the images that do not) with a train / test split of 80% (80% used for training and 20% for test).&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;train_test_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'data/with_mask'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'data/train/training_with_mask'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'data/test/test_with_mask'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;train_test_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'data/without_mask'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;'data/train/training_without_mask'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'data/test/test_without_mask'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  The model
&lt;/h2&gt;

&lt;p&gt;The definition of the model is presented below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="n"&gt;Conv2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'relu'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IMG_WIDTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IMG_HEIGHT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="n"&gt;MaxPooling2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Conv2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'relu'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;MaxPooling2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Conv2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;padding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'same'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'relu'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;MaxPooling2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Flatten&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="n"&gt;Dropout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="n"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'relu'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;activation&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'softmax'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# dense layer has a shape of 2 as we have only 2 classes 
&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;optimizer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'adam'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'binary_crossentropy'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metrics&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'accuracy'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The model consists of 10 layers in total. &lt;br&gt;
The first 6 layers form 3 sequential &lt;strong&gt;Convolution - ReLu - Pooling&lt;/strong&gt; groups.&lt;br&gt;
Then, a &lt;strong&gt;flatten layer is applied&lt;/strong&gt; to reshape the output of the CNN to a single dimension.&lt;br&gt;
After the flatten layer, a &lt;strong&gt;dropout layer&lt;/strong&gt; is applied. This layer &lt;strong&gt;randomly drops 30% (rate = 0.3) of the tensors in order to avoid overfitting&lt;/strong&gt;. &lt;br&gt;
In the end, &lt;strong&gt;a fully connected (dense) layer is applied&lt;/strong&gt; that classifies the images based on the features extracted in the previous layers of the CNN and &lt;strong&gt;the final layer outputs the probability of each class label&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We also use &lt;strong&gt;binary_crossentropy&lt;/strong&gt; as the loss function because our data contain only 2 classes.&lt;/p&gt;
&lt;h2&gt;
  
  
  Training the model
&lt;/h2&gt;

&lt;p&gt;We train the model with the following function.&lt;br&gt;
First, we open 2 training streams ("flows") from the 2 directories of train and test (validation) images.&lt;br&gt;
We also save checkpoints during training in separate directories for each checkpoint.&lt;br&gt;
Finally, we call the fit_generator function of the model and training begins.&lt;br&gt;
During the process, we keep track of training and validation accuracy and loss (we will use the values later to plot learning curves).&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;trainModel&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
  &lt;span class="n"&gt;training_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"data/train"&lt;/span&gt;
  &lt;span class="n"&gt;train_datagen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageDataGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rescale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;rotation_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;width_shift_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;height_shift_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;shear_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;zoom_range&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;horizontal_flip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                     &lt;span class="n"&gt;fill_mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'nearest'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;train_generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;train_datagen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flow_from_directory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;training_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                                      &lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                                      &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IMG_WIDTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IMG_HEIGHT&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="n"&gt;validation_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"data/test"&lt;/span&gt;
  &lt;span class="n"&gt;validation_datagen&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ImageDataGenerator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rescale&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;validation_generator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;validation_datagen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flow_from_directory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;validation_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                                           &lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                                                           &lt;span class="n"&gt;target_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IMG_WIDTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IMG_HEIGHT&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="n"&gt;checkpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ModelCheckpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'model-{epoch:03d}.model'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;monitor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'val_loss'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;verbose&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;save_best_only&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'auto'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fit_generator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;train_generator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;epochs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;epochs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;validation_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;validation_generator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;checkpoint&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;
  &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'accuracy'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;val_acc&lt;/span&gt;
  &lt;span class="n"&gt;val_acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'val_accuracy'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;loss&lt;/span&gt;
  &lt;span class="n"&gt;loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'loss'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="k"&gt;global&lt;/span&gt; &lt;span class="n"&gt;val_loss&lt;/span&gt;
  &lt;span class="n"&gt;val_loss&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'val_loss'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then, we label the outputs of the CNN ans apply colors to the results (red for without mask, green with mask) as follows:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;labels_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;'without mask'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;'with mask'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;color_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Implementing face detection
&lt;/h2&gt;

&lt;p&gt;Inspired by &lt;a href="https://towardsdatascience.com/covid-19-face-mask-detection-using-tensorflow-and-opencv-702dd833515b"&gt;this face and mask detection article&lt;/a&gt;, I used the OpenCV framework to implement live face detection using the default webcam of the computer. I used the very common &lt;strong&gt;Haar Feature-based Cascade Classifiers&lt;/strong&gt; for detecting the features of the face. This cascade classifier is designed by OpenCV to detect the frontal face by training thousands of images.&lt;/p&gt;

&lt;p&gt;Face and mask detection is performed in the following code (courtesy of &lt;a href="https://towardsdatascience.com/@mk.gurucharan"&gt;Gurucharan M K&lt;/a&gt;).&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Initializing webcam to live preview face mask detection ROIs on faces
# Seen this in this repo https://github.com/mk-gurucharan/Face-Mask-Detection
&lt;/span&gt;&lt;span class="n"&gt;face_clsfr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CascadeClassifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'haarcascade_frontalface_default.xml'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;labels_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;'without mask'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s"&gt;'with mask'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;color_dict&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;

&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
&lt;span class="n"&gt;webcam&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;VideoCapture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;classifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CascadeClassifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'haarcascade_frontalface_default.xml'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;webcam&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;im&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;flip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#Flip to act as a mirror
&lt;/span&gt;
    &lt;span class="c1"&gt;# Resize the image to speed up detection
&lt;/span&gt;    &lt;span class="n"&gt;mini&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;faces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;classifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;detectMultiScale&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;mini&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Draw rectangles around each face
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;faces&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;face_img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;resized&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;face_img&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="n"&gt;IMG_WIDTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;IMG_HEIGHT&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;normalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resized&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;255.0&lt;/span&gt;
        &lt;span class="n"&gt;reshaped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reshape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;IMG_WIDTH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;IMG_HEIGHT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;reshaped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;vstack&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;reshaped&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;predict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reshaped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;label&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;),((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="n"&gt;color_dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rectangle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;),((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="n"&gt;color_dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;putText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;labels_dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FONT_HERSHEY_DUPLEX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;imshow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Mask Detection'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;im&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;waitKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;27&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
&lt;span class="n"&gt;webcam&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;release&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;cv2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;destroyAllWindows&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NoPTy5JJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sd0bi1n8t4iwvg1l3707.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NoPTy5JJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sd0bi1n8t4iwvg1l3707.gif" alt="Live face mask detection" width="880" height="533"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Benchmarks
&lt;/h2&gt;

&lt;p&gt;The learning curves (training and validation accuracy and loss) of the model are the following for 30 epochs of training:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vfOfEiIb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8cnb64411xlmqxh2efiq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vfOfEiIb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8cnb64411xlmqxh2efiq.png" alt="Learning curves" width="880" height="437"&gt;&lt;/a&gt;&lt;br&gt;
As you can see we achieved an accuracy of more than &lt;strong&gt;98% in the validation dataset&lt;/strong&gt; which is nice!&lt;/p&gt;

&lt;p&gt;In my 2.5 GHz i7, 16 GB Ram MacBook Pro, the model took almost 17 minutes to train.&lt;/p&gt;
&lt;h2&gt;
  
  
  Full project
&lt;/h2&gt;

&lt;p&gt;Full project is available in this Github repository&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/petrosDemetrakopoulos"&gt;
        petrosDemetrakopoulos
      &lt;/a&gt; / &lt;a href="https://github.com/petrosDemetrakopoulos/face-mask-detector"&gt;
        face-mask-detector
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Face mask detection with Tensorflow and Keras CNNs
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Face mask detection with Tensorflow CNNs&lt;/h1&gt;
&lt;p&gt;COVID-19 has been an inspiration for many software and data engineers during the last months
This project demonstrates how a Convolutional Neural Network (CNN) can detect if a person in a picture is wearing a face mask or not
As you can easily understand the applications of this method may be very helpful for the prevention and the control of COVID-19 as it could be used in public places like airports, shopping malls etc.&lt;/p&gt;
&lt;h2&gt;
Defining the problem&lt;/h2&gt;
&lt;p&gt;Detecting if an image contains a person wearing a mask or not is a simple &lt;strong&gt;classification problem&lt;/strong&gt;
We have to classify the images between &lt;strong&gt;2 discrete classes&lt;/strong&gt;: The ones that contain a face mask and the ones that do not.&lt;/p&gt;
&lt;h2&gt;
The dataset&lt;/h2&gt;
&lt;p&gt;Hopefully, I found a dataset containing faces with and without masks online. It is available on this &lt;a href="https://github.com/prajnasb/observations/tree/master/experiements/data"&gt;github link&lt;/a&gt;
It contains 1,376…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/petrosDemetrakopoulos/face-mask-detector"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://towardsdatascience.com/covid-19-face-mask-detection-using-tensorflow-and-opencv-702dd833515b"&gt;COVID-19: Face Mask Detection using TensorFlow and OpenCV&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/prajnasb/observations/tree/master/experiements/data"&gt;Face masks images dataset&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/machine-learning/practica/image-classification/convolutional-neural-networks"&gt;Google developer - ML Practicum: Image Classification&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.saama.com/different-kinds-convolutional-filters/"&gt;saama - Different Kinds of Convolutional Filters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tensorflow.org/tutorials/images/classification"&gt;Tensorflow documentation - Image classification&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>python</category>
      <category>tensorflow</category>
      <category>machinelearning</category>
      <category>datascience</category>
    </item>
    <item>
      <title>11 weird questions I was asked in interviews</title>
      <dc:creator>Petros Demetrakopoulos</dc:creator>
      <pubDate>Wed, 24 Jun 2020 16:05:59 +0000</pubDate>
      <link>https://dev.to/demetrakopetros/11-weird-questions-i-was-asked-in-interviews-1hnm</link>
      <guid>https://dev.to/demetrakopetros/11-weird-questions-i-was-asked-in-interviews-1hnm</guid>
      <description>&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How much is 17x17?&lt;/strong&gt;&lt;br&gt;
The answer is 289 and of course, I answered it wrong. However, the recruiter which asked this question mentioned that he did it to “check how I think” so I believe he would like to see me thinking that 17x17 is 17^2 which is (10 + 7)^2 which expands to 10^2 + 2x10x7 + 7^2 which equals 100 + 49 + 70x2 = 289.&lt;br&gt;
Pretty weird though.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Do you know how Shazam works?&lt;/strong&gt;&lt;br&gt;
In layman’s terms, Shazam captures a &lt;strong&gt;sound sample&lt;/strong&gt; of a song and then analyses it into a &lt;strong&gt;table of frequencies&lt;/strong&gt; that the song contains and how frequently these frequencies are presented in a specific song. This distribution of frequencies is unique for each song and thus a song can be uniquely identified by it. This is achieved with algorithms and methods like &lt;strong&gt;Discrete Fourier Transform (DFT)&lt;/strong&gt; derived from the fields of signal processing, mathematics, and physics. You can find more about how Shazam works on this awesome &lt;a href="http://coding-geek.com/how-shazam-works/"&gt;blog post&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What was the most self-explanatory and streamlined solution you provided in a complex programming problem you faced?&lt;/strong&gt;&lt;br&gt;
As you can guess, there is no right or wrong answer to this question and it is personal and different for everyone. I answered with a solution I provided to a queue waiting problem. My team and I solved the problem in the database level of the app with SQL stored procedures and triggers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;What is the most important thing that your parents offered you?&lt;/strong&gt;&lt;br&gt;
This was a tricky one. I answered that one of the most important things that my parents offered me was &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tuition in 2 very good private schools. I explained that the overall experience that these schools offered me was much more than just better teachers and better education. These 2 schools offered me many opportunities in culture, sports, science clubs, etc. &lt;/li&gt;
&lt;li&gt;My parents also offered me many stimuli and incentives to fill my spare time. Walks in art exhibitions, museums, performance of science experiments at home during the weekends, and of course coding were some of them.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What is the difference between a process and a thread?&lt;/strong&gt;&lt;br&gt;
I had to remember some basic principles from the Operating Systems course in university to answer this correctly. The difference is crucial and simple: Both threads and processes are “independent sequences of execution”. However, &lt;strong&gt;threads that run on the same process, run in a shared memory space&lt;/strong&gt; while &lt;strong&gt;processes run in separate memory spaces&lt;/strong&gt;. This &lt;a href="https://stackoverflow.com/questions/200469/what-is-the-difference-between-a-process-and-a-thread"&gt;StackOverflow answer&lt;/a&gt; makes it pretty clear. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Would it be able to create a server running in a PC monitoring all the transactions of Ethereum blockchain in real-time?&lt;/strong&gt;&lt;br&gt;
The answer is no. According to &lt;a href="https://ethereum.stackexchange.com/questions/82053/syncing-keeps-behind-the-blockchain"&gt;this StackExchange answer&lt;/a&gt;, “Syncing the Ethereum blockchain with Geth in --fast mode has two phases running in parallel: block sync and state trie download. Both phases need to be done in order to have a full node and switch to full mode where every transaction is executed and verified. The block sync downloads all the block information (header, transactions). This phase uses a lot of CPU and space to store all the data. However, in fast mode no transactions are executed, so we do not have any account state available (ie. balances, nonces, smart contract code and data). Geth needs to download and cross-check with the latest block the state trie. This phase is called state trie download and usually takes longer than the block sync. When you are between 64 and 128 blocks behind, it usually means &lt;strong&gt;you finished the block sync phase and during the state trie download phase, the block number count will always oscillate between 64 and 128 blocks behind the latest block mined on Ethereum&lt;/strong&gt;. This is normal until the state trie download phase ends and your node is fully synced. However, using an HDD, you might not be able to keep up and have a high enough disk write rate to catch the head (latest state entry). &lt;br&gt;
My personal experience is that the SSD in my MacBook Pro &lt;strong&gt;failed to sync too due to disk rate and disk space&lt;/strong&gt;, so it is not possible to sync the entire Ethereum blockchain with a typical personal computer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Why do you prefer React over Angular?&lt;/strong&gt;&lt;br&gt;
I know that React is a library and Angular is a framework and thus comparing them may seem like comparing Apples to Oranges. However I answered that I prefer React because it is more lightweight in terms of payload (in front-end development, the payload of a library or framework is something that a developer should really care about because it may be used by mobile or really slow internet connections) while it offers exactly the same functionality. I also explained that the so-called 2-way binding functionality of Angular is not really missing from React, as &lt;strong&gt;React accomplishes the same result using state&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Did your team write tests in your previous job?&lt;/strong&gt;&lt;br&gt;
The answer there was pretty simple and straightforward. Yes, in my previous job the team wrote tests, we had an organized CI/CD track that ran all the tests before the deployment. I also mentioned we used multiple git branches for the different development and deployment stages (development, staging, production, etc.)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What is the difference between git rebase and git merge?&lt;/strong&gt;&lt;br&gt;
Git rebase and merge are both used to integrate changes from one branch into another. Their difference lies in how this result is achieved. The main difference is that &lt;strong&gt;git rebase moves a branch into master as it is&lt;/strong&gt; while &lt;strong&gt;merge adds a new commit (a merge commit) preserving the history&lt;/strong&gt; and chronological order. We could say that merge preserves the commit history as rebase re-writes it. You can learn more about git rebase vs git merge in this awesome &lt;a href="https://www.atlassian.com/git/tutorials/merging-vs-rebasing"&gt;Atlassian tutorial&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What is the difference between UNION and UNION ALL in SQL?&lt;/strong&gt;&lt;br&gt;
UNION SQL command is used to combine the results of 2 or more SELECT statements. The difference between UNION and UNION ALL is that &lt;strong&gt;UNION eliminates duplicate records&lt;/strong&gt; while &lt;strong&gt;UNION ALL preserves them&lt;/strong&gt;. As you can imagine, using UNION instead of UNION ALL has a drawback in performance since the DB server must do additional work to remove duplicate rows.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;From which club did you get your sailing license?&lt;/strong&gt;&lt;br&gt;
A funny one, probably the recruiter used it as an ice-breaker. He was a licensed open sea sailing captain too, so he asked in which club I did the courses and if I had ever taken part in sailing races.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Apart from the classic interview questions, these were some that I found interesting and/or weird. If you have any experience with interesting or weird interview questions, feel free to discuss them in the comment section.&lt;/p&gt;

</description>
      <category>learning</category>
      <category>career</category>
    </item>
    <item>
      <title>Unit testing Node.JS APIs</title>
      <dc:creator>Petros Demetrakopoulos</dc:creator>
      <pubDate>Sat, 18 Apr 2020 11:56:36 +0000</pubDate>
      <link>https://dev.to/demetrakopetros/unit-testing-node-js-apis-c2k</link>
      <guid>https://dev.to/demetrakopetros/unit-testing-node-js-apis-c2k</guid>
      <description>&lt;p&gt;As a professional software developer dedicated to Node.js RESTful APIs, I have come to the following conclusion:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Developers are not paid to write code.&lt;br&gt;
They are paid to deliver tech&lt;br&gt;
&lt;strong&gt;solutions&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And these solutions should be...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Concrete and robust&lt;/li&gt;
&lt;li&gt;Have high availability no matter the load&lt;/li&gt;
&lt;li&gt;Reliable&lt;/li&gt;
&lt;li&gt;Secure&lt;/li&gt;
&lt;li&gt;Cost-effective&lt;/li&gt;
&lt;li&gt;Maintainable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Developers should also be able to &lt;strong&gt;provide evidence&lt;/strong&gt; that their solutions match the criteria mentioned above. They should also be able to &lt;strong&gt;detect and fix&lt;/strong&gt; easily and fast any bug or issue that may occur.&lt;/p&gt;

&lt;p&gt;And that's where &lt;strong&gt;Unit testing&lt;/strong&gt; comes in&lt;/p&gt;

&lt;h1&gt;
  
  
  Definition
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Unit Testing is a level of software testing where individual units/ components of a software are tested. The purpose is to validate that each unit of the software performs as designed.&lt;br&gt;
Source: &lt;a href="http://softwaretestingfundamentals.com/" rel="noopener noreferrer"&gt;softwaretestingfundamentals.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  But which are the units in an API?
&lt;/h1&gt;

&lt;p&gt;The units in an API consist of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API requests

&lt;ul&gt;
&lt;li&gt;HTTP method (i.e GET, POST, PUT etc.) API endpoint (i.e /v1/posts)&lt;/li&gt;
&lt;li&gt;Request parameters&lt;/li&gt;
&lt;li&gt;Request headers&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Request Body • Models

&lt;ul&gt;
&lt;li&gt;Properties / fields &lt;/li&gt;
&lt;li&gt;Model methods&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Learning by example: An example API
&lt;/h1&gt;

&lt;p&gt;For the purposes of this article, we will use an example API for a classic book  Library (yes, the original one where you can borrow books, study, etc.)&lt;/p&gt;

&lt;p&gt;The API will be composed of the following elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Entities / Models&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Books &lt;/li&gt;
&lt;li&gt;Users&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Endpoints&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GET /users &lt;/li&gt;
&lt;li&gt;POST /user &lt;/li&gt;
&lt;li&gt;GET /books &lt;/li&gt;
&lt;li&gt;POST /book&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;The endpoints have the form shown in the following screenshots:&lt;br&gt;
We use &lt;a href="https://www.npmjs.com/package/faker" rel="noopener noreferrer"&gt;faker.js&lt;/a&gt; to generate the dummy data that the API will use.&lt;/p&gt;

&lt;p&gt;GET /users endpoint&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy3p4so4dnrbahhng4q28.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy3p4so4dnrbahhng4q28.png" alt="GET /users"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;POST /user endpoint&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1jv2m2f6p3thqzr3pc9z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1jv2m2f6p3thqzr3pc9z.png" alt="POST /user"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GET /books endpoint&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmcgu7btsrp160bn4ts5g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmcgu7btsrp160bn4ts5g.png" alt="GET /books"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;POST /book endpoint&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F14px0kvacvtbxf4yzmg9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F14px0kvacvtbxf4yzmg9.png" alt="POST /book"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So far so good. I think it is crystal what each endpoint does and the form of data that it responds with.&lt;/p&gt;

&lt;p&gt;An example response for the GET /users endpoint looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0s8hj3zo4vqcdlb8hi4u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0s8hj3zo4vqcdlb8hi4u.png" alt="Example response"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  But what do we really want to test?
&lt;/h1&gt;

&lt;p&gt;By writing unit tests for an API, we try to answer questions like these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does &lt;strong&gt;GET /users&lt;/strong&gt; always responds with an &lt;strong&gt;array of user objects&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Does &lt;strong&gt;POST /book&lt;/strong&gt; always responds with the &lt;strong&gt;book object submitted&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Does &lt;strong&gt;POST /user&lt;/strong&gt; responds with the right error code when one or more &lt;strong&gt;required fields are missing&lt;/strong&gt;?&lt;/li&gt;
&lt;li&gt;Does &lt;strong&gt;POST /user&lt;/strong&gt; responds with the right error code when email &lt;strong&gt;does not have the correct format&lt;/strong&gt;?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, there are many more questions that we may want to answer to be sure that our API works as expected but for our example, those are some important ones.&lt;/p&gt;
&lt;h1&gt;
  
  
  Let’s grab a cup of coffee (or tea ?)
&lt;/h1&gt;

&lt;p&gt;The 2 main libraries we use to write unit tests for Node.JS applications are &lt;a href="https://www.npmjs.com/package/mocha" rel="noopener noreferrer"&gt;Mocha&lt;/a&gt; which is the main unit testing framework and &lt;a href="https://www.npmjs.com/package/chai" rel="noopener noreferrer"&gt;Chai&lt;/a&gt; which is the assertion library. Chai provides the functions that make the checks we want to perform a lot easier. &lt;/p&gt;

&lt;p&gt;i.e&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;should&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;should&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;have&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;property&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;phone&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Chai library has 4 main interfaces that do the same thing with&lt;br&gt;
different syntax:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;should &lt;/li&gt;
&lt;li&gt;assert &lt;/li&gt;
&lt;li&gt;expect&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;i.e the following 3 lines perform exactly the same test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;should&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;typeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="nx"&gt;string&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  A look in the &lt;code&gt;package.json&lt;/code&gt; file of our project
&lt;/h1&gt;

&lt;p&gt;In order to run tests with the default &lt;code&gt;npm test command&lt;/code&gt; we should add the following value in the &lt;code&gt;scripts&lt;/code&gt; key of our &lt;code&gt;package.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nyc mocha --timeout 10000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We set the timeout for each test case (a test case performs an API call) to 10K ms (or 10s).&lt;/p&gt;

&lt;h1&gt;
  
  
  The anatomy of a test
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqeq8danptt9wb61s0b1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqeq8danptt9wb61s0b1z.png" alt="Anatomy of a test"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see a test is composed of &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The dependencies (common for many test cases)&lt;/li&gt;
&lt;li&gt;A name and a description&lt;/li&gt;
&lt;li&gt;The API call&lt;/li&gt;
&lt;li&gt;The actual tests (assertions)&lt;/li&gt;
&lt;li&gt;The callback that notifies mocha library that the test has completed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Coverage reports and nyc
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/nyc" rel="noopener noreferrer"&gt;nyc&lt;/a&gt; is a tool that reports how much of the total code is covered by the tests we have written. It also reports all the uncovered lines so to know where to look and what tests to write.&lt;/p&gt;

&lt;p&gt;A coverage report after the completion of the tests looks like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F313yrws5zv54hnc6v0le.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F313yrws5zv54hnc6v0le.png" alt="Coverage report"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Some good practices regarding unit tests
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It is a good practice to &lt;strong&gt;save the different payloads&lt;/strong&gt; we use to test POST endpoints &lt;strong&gt;in separate .txt or .json files&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We should also create different test declarations for different things /&lt;br&gt;
functions we want to check.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We should also try to write tests in order to form different “scenarios”. &lt;br&gt;
i.e The DB is initially empty, so we POST a new user, then the user created POSTs a new book, then we DELETE the book and then the user etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We should also write tests to check &lt;strong&gt;error codes and errors&lt;/strong&gt;. Bugs and issues may be hidden in the validation logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We should also write tests checking &lt;strong&gt;access level&lt;/strong&gt; if our API has different user types with different access levels&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, we should try to reach the higher coverage we can. However, we should always keep in mind that it is impossible to reach 100%.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  That's all folks!
&lt;/h1&gt;

&lt;p&gt;I hope you enjoyed it and that it will help you to write unit tests for your Node.JS API in the future.&lt;/p&gt;

</description>
      <category>node</category>
      <category>testing</category>
      <category>javascript</category>
      <category>api</category>
    </item>
    <item>
      <title>Security in Node.JS and Express: The bare minimum - Part 3.</title>
      <dc:creator>Petros Demetrakopoulos</dc:creator>
      <pubDate>Wed, 15 Apr 2020 14:27:56 +0000</pubDate>
      <link>https://dev.to/demetrakopetros/security-in-node-js-and-express-the-bare-minimum-part-3-54f3</link>
      <guid>https://dev.to/demetrakopetros/security-in-node-js-and-express-the-bare-minimum-part-3-54f3</guid>
      <description>&lt;p&gt;In the previous part, we covered&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;XSS Attacks&lt;/li&gt;
&lt;li&gt;SQL injections&lt;/li&gt;
&lt;li&gt;RegEx Denial of Service&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/demetrakopetros" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EH54IcUC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--iQp-mlrm--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/36805/af2e939b-ec6a-40c2-86bc-28d4ed138989.JPG" alt="demetrakopetros"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/demetrakopetros/security-in-node-js-and-express-the-bare-minimum-part-2-ll4" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Security in Node.JS and Express: The bare minimum - Part 2.&lt;/h2&gt;
      &lt;h3&gt;Petros Demetrakopoulos ・ Apr 10 '20 ・ 3 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#security&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;In this part, we will cover&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cross-Site Request Forgery Attacks (CSRF)&lt;/li&gt;
&lt;li&gt;Rate Limiting &lt;/li&gt;
&lt;li&gt;Data Sanitization&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Cross-Site Request Forgery
&lt;/h1&gt;

&lt;p&gt;Cross-Site Request Forgery according to &lt;a href="https://owasp.org/www-community/attacks/csrf"&gt;OWASP&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cross-Site Request Forgery (CSRF) is an attack that forces an end user to execute unwanted actions on a web application in which they’re currently authenticated. CSRF attacks specifically target state-changing requests, not theft of data, since the attacker has no way to see the response to the forged request. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In order to prevent this kind of attacks, we should implement a &lt;strong&gt;synchronized CSRF tokens policy&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;CSRF token is a simple string set when the user requests a page that contains a form and expects the same CSRF token when a POST request is made. If the CSRF tokens do not match or if the CSRF token is not in the form data, the POST request is not allowed. CSRF token is &lt;strong&gt;unique for each user session&lt;/strong&gt; and most of the times it expires in a given time span.&lt;/p&gt;

&lt;p&gt;In Express applications we can implement a CSRF policy with the help of &lt;a href="https://www.npmjs.com/package/csurf"&gt;csurf&lt;/a&gt; npm package. &lt;br&gt;
The package can be used in one line and it handles everything related to the CSRF tokens for all the users.&lt;/p&gt;

&lt;p&gt;So in the back-end the correct setup looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;csrf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;csurf&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;csrf&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_csrf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;csrfToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the front-end looks like this for each form.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;form&lt;/span&gt; &lt;span class="na"&gt;method=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt; &lt;span class="na"&gt;action=&lt;/span&gt;&lt;span class="s"&gt;“changeEmail"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"hidden"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"_csrf"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"_csrf"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;“newEmail"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/form&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Rate Limiting
&lt;/h1&gt;

&lt;p&gt;One other crucial aspect of the security of your Express application is &lt;strong&gt;rate limiting&lt;/strong&gt;. As you may already know, rate limiting is the policy that control the rate of requests that your server can receive from a specific user and / or IP address. In that way we prevent &lt;a href="https://en.wikipedia.org/wiki/Denial-of-service_attack"&gt;DoS attacks&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/express-rate-limit"&gt;express-rate-limit&lt;/a&gt; npm package enables us to apply policies like the ones mentioned above in a really easy way.&lt;/p&gt;

&lt;p&gt;i.e&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;rateLimit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express-rate-limit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

 &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;trust proxy&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// add this line only if your server is behind a proxy&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;limiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rateLimit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;windowMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 15 minutes&lt;/span&gt;
  &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// limit each IP to 100 requests per windowMs&lt;/span&gt;
&lt;span class="na"&gt;delayMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;// disable delaying - user has full speed until the max limit is reached&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limiter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// applies rate limiting policy to every endpoint of the server&lt;/span&gt;
&lt;span class="c1"&gt;// we could also apply policies for specific routes or even different policies for each route&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.npmjs.com/package/express-rate-limit"&gt;express-rate-limit&lt;/a&gt; allows us to apply rate limiting policies to all the endpoints of our Express server or even different policies for each route.&lt;/p&gt;

&lt;p&gt;i.e This example applies a rate limiting policy only to the enpoints starting with /api.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;rateLimit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express-rate-limit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;apiLimiter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rateLimit&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;windowMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 15 minutes&lt;/span&gt;
  &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// only apply to requests that begin with /api/&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;apiLimiter&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Important note:&lt;/strong&gt; Static resources such as images, CSS stylesheets, front-end Javascript scripts count for requests as well &lt;strong&gt;if we serve them through our Express server&lt;/strong&gt; (which is a bad practice anyway, we should prefer CDN networks for static resources).&lt;/p&gt;

&lt;h1&gt;
  
  
  Data sanitisation and validation
&lt;/h1&gt;

&lt;p&gt;It is an important process that must take place in every endpoint where the user interacts with the server &lt;strong&gt;by submitting data&lt;/strong&gt;. It protects the server from most of the flaws mentioned in this serie of articles. When we are validating data, we are interested in checks like &lt;strong&gt;"Is this a correct e-mail address?"&lt;/strong&gt;, &lt;strong&gt;"Is it an Integer?"&lt;/strong&gt;, &lt;strong&gt;"Is it a valid telephone number?"&lt;/strong&gt; etc.&lt;/p&gt;

&lt;p&gt;A very usefull npm package that helps us perform this kind of checks in user input is &lt;a href="https://www.npmjs.com/package/express-validator"&gt;express-validator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/express-validator"&gt;express-validator&lt;/a&gt; allows us to define "check schemas" for each endpoint in pure JSON. It also allows us to set the error messages sent back to the user if a validation for a field fails.&lt;/p&gt;

&lt;p&gt;An example is given below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/user/:id/password&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;checkSchema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// the location of the field can be one or more of 'body', 'cookies', &lt;/span&gt;
   &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;headers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;params&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
   &lt;span class="c1"&gt;// If omitted, all request locations will be checked&lt;/span&gt;
     &lt;span class="na"&gt;in&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;params&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;query&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
     &lt;span class="na"&gt;isInt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="na"&gt;errorMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ID is wrong&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
   &lt;span class="p"&gt;},&lt;/span&gt;
   &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;isLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="na"&gt;errorMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Password should be at least 7 characters long&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;express-validator offers many useful keys and functions such as &lt;code&gt;isIn()&lt;/code&gt;, &lt;code&gt;exists()&lt;/code&gt;, &lt;code&gt;isUUID()&lt;/code&gt;, &lt;code&gt;isPostalCode()&lt;/code&gt;, trimimng functions etc. It also allows us to implement custom validation and sanitisation logics.&lt;/p&gt;

&lt;h1&gt;
  
  
  That's all folks (for now...)
&lt;/h1&gt;

&lt;p&gt;I hope you find it interesting and it will help you build more secure and robust Node.JS and Express apps.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Security in Node.JS and Express: The bare minimum - Part 2.</title>
      <dc:creator>Petros Demetrakopoulos</dc:creator>
      <pubDate>Fri, 10 Apr 2020 09:28:43 +0000</pubDate>
      <link>https://dev.to/demetrakopetros/security-in-node-js-and-express-the-bare-minimum-part-2-ll4</link>
      <guid>https://dev.to/demetrakopetros/security-in-node-js-and-express-the-bare-minimum-part-2-ll4</guid>
      <description>&lt;p&gt;In the previous part, we covered&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server side JS injection&lt;/li&gt;
&lt;li&gt;“Use strict”&lt;/li&gt;
&lt;li&gt;Helmet&lt;/li&gt;
&lt;li&gt;Changing default error pages&lt;/li&gt;
&lt;li&gt;Proper session management&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/demetrakopetros" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F36805%2Faf2e939b-ec6a-40c2-86bc-28d4ed138989.JPG" alt="demetrakopetros"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/demetrakopetros/security-in-node-js-and-express-the-bare-minimum-part-1-98o" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Security in Node.JS and Express: The bare minimum - Part 1.&lt;/h2&gt;
      &lt;h3&gt;Petros Demetrakopoulos ・ Apr 6 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#security&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;In this part, we will cover&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;XSS Attacks&lt;/li&gt;
&lt;li&gt;SQL injections &lt;/li&gt;
&lt;li&gt;RegEx Denial of Service&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  XSS Attacks in general
&lt;/h1&gt;

&lt;p&gt;XSS attacks (or Cross - Site Scripting) allows intruders to execute scripts in the victims’ browser. In that way, they can access cookies, session tokens and other sensitive info or redirect users to malicious sites. It is one of the most common ways an intruder can take over a webpage.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
Let's say we have the following sign-up form that sends data to our Express server:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftwa5ukoldgfizh1kplr1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftwa5ukoldgfizh1kplr1.png" alt="A typical sign-up form"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we do nothing about it, 'alert(document.cookie)' will be saved in the username field in our database backend and when we fetch and render the username of the specific user in the future, the user will see the following alert.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyfbv8f18j50v95bo7n3v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyfbv8f18j50v95bo7n3v.png" alt="Cookie alert"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can imagine, this vulnerability may have catastrophic consequences as it may expose critical information and data. Actually some of the most famous attacks in the web have been performed by exploiting this vulnerability. A classic example is this &lt;a href="https://www.theguardian.com/technology/2014/jun/11/twitter-tweetdeck-xss-flaw-users-vulnerable" rel="noopener noreferrer"&gt;2014 attack in Twitter&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  XSS Attacks - How to prevent them
&lt;/h2&gt;

&lt;p&gt;There is a bunch of things we can do to secure our Express server for XSS-attacks. First of all, we should always perform &lt;strong&gt;data validation and sanitization&lt;/strong&gt;. This means that for every incoming request we should check that the input parameters given by the user are in the correct format, the one that the server and the database expect to be. Another useful tip is to set the cookie &lt;code&gt;httpOnly&lt;/code&gt; value to &lt;code&gt;true&lt;/code&gt; because it prevents cookies from being accessed by browser JS scripts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;session&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s3Cur3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, we should always HTML Escape data before inserting it into HTML Elements (ex: convert &amp;amp; to &amp;amp; and &amp;lt; to &amp;lt; etc). This will probably neutralize some XSS threats. We should also do this for JSON values presented in an HTML context and read the data with &lt;code&gt;JSON.parse()&lt;/code&gt;.&lt;br&gt;
Finally, we should use &lt;a href="https://www.npmjs.com/package/xss" rel="noopener noreferrer"&gt;“XSS” npm package&lt;/a&gt; that will perform many of the counter-measures mentioned above for use.&lt;/p&gt;
&lt;h1&gt;
  
  
  SQL injections in general
&lt;/h1&gt;

&lt;p&gt;Let's that in a login endpoint, we receive the username and the password of the user in the following way (to simplify the case, let's assume that no password hashing policy is performed).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/login&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;sql&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SELECT * FROM Users WHERE Name ="&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;" AND Pass ="&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;password&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// and then executing the query in our SQL databse&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What if the malicious user type  " or “"=" in username and password fields ?&lt;br&gt;
thw SQL  query that we are ready to execute will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM Users WHERE Name ="" or ""="" AND Pass ="" or ""="" 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;OR ""=""&lt;/code&gt; condition is always true!&lt;br&gt;
So the query returns all the rows of “Users” table.&lt;/p&gt;
&lt;h2&gt;
  
  
  SQL injections - How to prevent them
&lt;/h2&gt;

&lt;p&gt;Once again, data validation and sanitization is the best way to eliminate these threats. NPM Packages like &lt;a href="https://www.npmjs.com/package/sqlstring" rel="noopener noreferrer"&gt;sqlstring&lt;/a&gt; ,  escape user input values and thus it makes the vulnerability very difficult for a malicious user to exploit it. Also, packages like &lt;a href="https://www.npmjs.com/package/sql-query-builder" rel="noopener noreferrer"&gt;sql-query-builder&lt;/a&gt; that offer you the ability to create SQL queries in a more structured way like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groupBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;are far better in security terms than string concatenated SQL queries.&lt;/p&gt;

&lt;h1&gt;
  
  
  RegEx Denial of Service
&lt;/h1&gt;

&lt;p&gt;Some Regular Expressions may be “unsafe” for some inputs, i.e &lt;code&gt;(a+)+&lt;/code&gt; regex is unsafe for input &lt;code&gt;aaaaaaaaaaaaaaaaaaaaa!&lt;/code&gt; as it will lead the regex evaluation to exponential time complexity causing the server to Denial of Service.&lt;/p&gt;

&lt;p&gt;Fortunately there is an NPM package that helps us detect vulnerable RegExes and it is called &lt;a href="https://www.npmjs.com/package/safe-regex" rel="noopener noreferrer"&gt;“safe-regex”&lt;/a&gt;&lt;br&gt;
It is used like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;safe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="nx"&gt;safe&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;safe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;regex&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will return a boolean value indicating if the regex is safe or not.&lt;/p&gt;

&lt;h1&gt;
  
  
  That's all folks (for now...)
&lt;/h1&gt;

&lt;p&gt;I hope you find it interesting and it will help you build more secure and robust Node.JS and Express apps.&lt;br&gt;
In the next part we will cover Cross-Site Request Forgery, Rate Limiting and Data Sanitization.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Security in Node.JS and Express: The bare minimum - Part 1.</title>
      <dc:creator>Petros Demetrakopoulos</dc:creator>
      <pubDate>Mon, 06 Apr 2020 08:43:48 +0000</pubDate>
      <link>https://dev.to/demetrakopetros/security-in-node-js-and-express-the-bare-minimum-part-1-98o</link>
      <guid>https://dev.to/demetrakopetros/security-in-node-js-and-express-the-bare-minimum-part-1-98o</guid>
      <description>&lt;p&gt;Node.JS is one of the most famous frameworks for developing the back-end part of an application. However, this does not mean in any way that it does not contain many vulnerabilities that the developer should be aware and take actions in order to neutralize them.&lt;/p&gt;

&lt;h1&gt;
  
  
  What we will cover in this article
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Server side JS injection&lt;/li&gt;
&lt;li&gt;“Use strict”&lt;/li&gt;
&lt;li&gt;Helmet&lt;/li&gt;
&lt;li&gt;Changing default error pages&lt;/li&gt;
&lt;li&gt;Proper session management&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Server side JS injection
&lt;/h1&gt;

&lt;p&gt;Also known as &lt;strong&gt;SSJS&lt;/strong&gt;.&lt;br&gt;
It is the case where user input is directly passed in native JS functions like &lt;code&gt;eval()&lt;/code&gt;,&lt;code&gt;setTimeout()&lt;/code&gt;, &lt;code&gt;setInterval()&lt;/code&gt; or &lt;code&gt;Function()&lt;/code&gt;. These functions enable the client to execute malicious Javascript code on the server-side. It could be a &lt;code&gt;process.exit()&lt;/code&gt; command that would kill the server or a call in file system. So we should simply avoid using these functions at any cost. These functions consist a bad practice even if we validate and sanitize user input data. In order to prevent it just use &lt;code&gt;JSON.parse()&lt;/code&gt;, it is much safer.&lt;/p&gt;
&lt;h1&gt;
  
  
  Use strict
&lt;/h1&gt;

&lt;p&gt;&lt;code&gt;"Use strict"&lt;/code&gt; literal must be declared in the top of every JS script of our Node.JS application. It enables "strict mode" which does not allow some actions such as using a variable without declaring it (i.e &lt;code&gt;x = 5.2&lt;/code&gt;), deleting objects, variables, functions etc. It also limits &lt;code&gt;eval()&lt;/code&gt; use cases and possible exploits.&lt;/p&gt;
&lt;h1&gt;
  
  
  Helmet
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/helmetjs/helmet"&gt;Helmet&lt;/a&gt; is an npm package (you can install it by typing &lt;code&gt;npm i helmet&lt;/code&gt;) that sets various HTTP headers that may consist a threat if left with the default values. It sets &lt;code&gt;Content-Security-Policy&lt;/code&gt; header and it also allows the developer to set the &lt;code&gt;X-Powered-By&lt;/code&gt; header to other than the default value, so the intruder is not aware of real stack behind the application running on the server. Finally, it protects you from a bunch of other things like clickjacking and disables client-side caching.&lt;/p&gt;
&lt;h1&gt;
  
  
  Changing default error pages
&lt;/h1&gt;

&lt;p&gt;There is no reason to hide &lt;code&gt;X-Powered-By&lt;/code&gt; header if we keep the default error pages of Express because the intruder can still understand that our server runs on Express. We can do so as shown in the snippet below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Handle 404&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;404&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;404: File Not Found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Handle 500&lt;/span&gt;
  &lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="err"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;500: Internal Server Error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Proper session management
&lt;/h1&gt;

&lt;p&gt;Session management may consist a possible threat too. &lt;br&gt;
The Express cookies we user should always have these 2 properties always set to &lt;code&gt;true&lt;/code&gt;:&lt;br&gt;
1) &lt;code&gt;httpOnly&lt;/code&gt; &lt;br&gt;
2) &lt;code&gt;secure&lt;/code&gt;&lt;br&gt;
The first one prevents cookies from being accessed by browser JS scripts and the second one forces that cookies can only be configured over secure HTTPS connections&lt;br&gt;
The correct cookies setup is shown in the snippet below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cookieParser&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;s3Cur3&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;httpOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;secure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;ephemeral&lt;/code&gt; cookie property is also very useul for security as it deletes the cookie when the browser is closed (if set to &lt;code&gt;true&lt;/code&gt;). So, it is very useful for apps that are being accessed by public computers.&lt;br&gt;
Finally, we should always destroy session and cookies on logout.&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  That's all folks (for now...)
&lt;/h1&gt;

&lt;p&gt;I hope you find it interesting and it will help you build more secure and robust Node.JS and Express apps.&lt;br&gt;
In the next part we will cover XSS Attacks, SQL and No-SQL injections and RegEx Denial of Service.&lt;/p&gt;

&lt;p&gt;Part 2 is also available in the link below:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/demetrakopetros" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EH54IcUC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://res.cloudinary.com/practicaldev/image/fetch/s--iQp-mlrm--/c_fill%2Cf_auto%2Cfl_progressive%2Ch_150%2Cq_auto%2Cw_150/https://dev-to-uploads.s3.amazonaws.com/uploads/user/profile_image/36805/af2e939b-ec6a-40c2-86bc-28d4ed138989.JPG" alt="demetrakopetros"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/demetrakopetros/security-in-node-js-and-express-the-bare-minimum-part-2-ll4" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Security in Node.JS and Express: The bare minimum - Part 2.&lt;/h2&gt;
      &lt;h3&gt;Petros Demetrakopoulos ・ Apr 10 '20 ・ 3 min read&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#javascript&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#node&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#security&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>node</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Generating Beatles-like lyrics with RNNs</title>
      <dc:creator>Petros Demetrakopoulos</dc:creator>
      <pubDate>Fri, 03 Apr 2020 10:13:22 +0000</pubDate>
      <link>https://dev.to/demetrakopetros/generating-beatles-like-lyrics-with-rnns-48ki</link>
      <guid>https://dev.to/demetrakopetros/generating-beatles-like-lyrics-with-rnns-48ki</guid>
      <description>&lt;p&gt;&lt;a href="https://github.com/petrosDemetrakopoulos/RNN-Beatles-lyrics-generator"&gt;Project link in Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The project is implemented in Python using Tensorflow.&lt;br&gt;
It is a word-based Recurrent neural network (RNN) inspired by this &lt;a href="https://www.tensorflow.org/tutorials/text/text_generation"&gt;Tensorflow tutorial&lt;/a&gt;.&lt;br&gt;
The model is trained in a corpus containing the song titles and the lyrics of many famous songs of Beatles.&lt;br&gt;
So, given a sequence of words from Beatles' lyrics, it can predict the next words. &lt;br&gt;
We could say that it is a model generating Beatle-like lyrics.&lt;/p&gt;
&lt;h1&gt;
  
  
  The corpus (aka training dataset)
&lt;/h1&gt;

&lt;p&gt;As we said the corpus (beatles_lyrics.txt) contains the song titles and the lyrics of many Beatles songs in the following format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Song title 1
-----------------
Lyric line 1
Lyric line 2
Lyric line 3
Lyric line 4
etc...

Song title 2
-----------------
Lyric line 1
Lyric line 2
Lyric line 3
Lyric line 4
etc...

etc...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I have manually created the corpus with the lyrics I found in &lt;a href="http://toti.eu.com/beatles/"&gt;this amazing site&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Data preprocessing
&lt;/h1&gt;

&lt;p&gt;As almost every machine learning model, training data need a bit of preprocessing before they are ready to be used as a training input for our RNN. &lt;br&gt;
We preprocess the initial corpus by doing the following tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convert all letters to lowercase&lt;/li&gt;
&lt;li&gt;Remove blank lines&lt;/li&gt;
&lt;li&gt;Remove special characters (such as ',' , '(' , ')' , '[' , ']' etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following function performs the preprocessing:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;stopChars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;'('&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;')'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;'['&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;']'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;'"'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# preprocessing the corpus by converting all letters to lowercase, 
# replacing blank lines with blank string and removing special characters
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;preprocessText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\t&lt;/span&gt;&lt;span class="s"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;processedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stopChars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;processedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;processedText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;processedText&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After the text preprocessing step, we need to convert it to a list of words.&lt;br&gt;
 This procedure is also known as "Tokenization".&lt;/p&gt;

&lt;p&gt;The following function performs the tokenization:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;corpusToList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;corpus&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;corpusList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;corpus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; 
  &lt;span class="n"&gt;corpusList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;corpusList&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;#removing empty strings from list
&lt;/span&gt;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;corpusList&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then, we trim each word for leading or trailing spaces / tabs.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;corpus_words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# trim words
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, it is time to find the unique words (aka vocabulary) from which our dataset is composed of.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;vocab&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;corpus_words&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In order to train our model, we need to represent words with numbers. So we map a specific number to each unique word of our corpus and vice versa by creating the following lookup tables. Then we represent the whole corpus as a list of numbers (&lt;code&gt;word_as_int&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Corpus length (in words):'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;corpus_words&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Unique words in corpus: {}'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="n"&gt;word2idx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
&lt;span class="n"&gt;idx2words&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;word_as_int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;array&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;word2idx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;corpus_words&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  The prediction process
&lt;/h1&gt;

&lt;p&gt;Our goal is to &lt;strong&gt;predict the next words that will follow in a sequence, given some starting words&lt;/strong&gt; (a start sequence).&lt;br&gt;
In layman's terms, &lt;strong&gt;RNNs are able to maintain an internal state that depends on the elements (in our case elements = sequences of words) that the RNN has previously "seen"&lt;/strong&gt;.&lt;br&gt;
So, we train the RNN to take as an input a sequence of words and predict the output, which is the following word at each time step. As you can easily understand, &lt;strong&gt;if we run the model for many time steps we generate sequences of words!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order to train it, we have to split our train dataset (aka corpus) in "batches" of sequences of words (as this is what we also want to predict). Then, we need to shuffle them, because we want to make the order with which the songs have been placed in the dataset indifferent for the RNN (and thus for the prediction it will do). If we do not shuffle them, RNN may learn the order of the songs in the corpus to and that &lt;strong&gt;may lead it to overfitting&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Creating training batches
&lt;/h1&gt;

&lt;p&gt;Now it is time to slice the corpus into training batches. Each batch should contain &lt;code&gt;seqLength&lt;/code&gt; words from the corpus.&lt;br&gt;
For each split sequence of words, there is also a &lt;strong&gt;target sequence&lt;/strong&gt; which has the same length as the training one and it is the same but one word shifted to the right. So, we slice the text into &lt;code&gt;seqLength+1&lt;/code&gt; words slices and we use the first &lt;code&gt;seqLength&lt;/code&gt; words as training sequence and we extract the target sequence as mentioned.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
Let's say our corpus contains the following verse:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I read the news today oh boy
About a lucky man who made the grade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, if the seqLength is 14, the training sequence will be :&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I read the news today oh boy
About a lucky man who made the
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;and the target sequence will be:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;read the news today oh boy
About a lucky man who made the grade.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;We do so with the following lines:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# The maximum length sentence we want for a single input in words
&lt;/span&gt;&lt;span class="n"&gt;seqLength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;examples_per_epoch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;corpus_words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seqLength&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# number of seqLength+1 sequences in the corpus
&lt;/span&gt;
&lt;span class="c1"&gt;# Create training / targets batches
&lt;/span&gt;&lt;span class="n"&gt;wordDataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;from_tensor_slices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word_as_int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sequencesOfWords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;wordDataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seqLength&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop_remainder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# generating batches of 10 words each, typically converting list of words (sequence) to string
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;split_input_target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="c1"&gt;# This is where right shift happens
&lt;/span&gt;  &lt;span class="n"&gt;input_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;target_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;input_text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target_text&lt;/span&gt; &lt;span class="c1"&gt;# returns training and target sequence for each batch
&lt;/span&gt;
&lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sequencesOfWords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;split_input_target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# dataset now contains a training and a target sequence for each 10 word slice of the corpus
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Shuffling the batches
&lt;/h1&gt;

&lt;p&gt;As we mentioned earlier, before we feed our training batches in our RNN, we have to shuffle them to prevent the RNN from learning the order of the songs in the corpus which may lead it to overfitting.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;BATCH_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt; &lt;span class="c1"&gt;# each batch contains 64 sequences. Each sequence contains 10 words (seqLength)
&lt;/span&gt;&lt;span class="n"&gt;BUFFER_SIZE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="c1"&gt;# Number of batches that will be processed concurrently
&lt;/span&gt;
&lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shuffle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BUFFER_SIZE&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BATCH_SIZE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;drop_remainder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;dataset&lt;/code&gt; now contains batches of 64 word sequence each, each sequence is filled in the previous step with 10 words.&lt;/p&gt;
&lt;h1&gt;
  
  
  The model
&lt;/h1&gt;

&lt;p&gt;Our RNN is composed of 3 layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Input layer. It maps the number representing each word to a vector with known dimensions (that are explicitly set)&lt;/li&gt;
&lt;li&gt;GRU (middle) layer: GRU stands for Gated Recurrent Units. The number of units that this layer contains is also explicitly set. This layer could also be replaced by a Long Short-Term Memory (LSTM) layer. More on LSTMs and GRUs in &lt;a href="https://towardsdatascience.com/illustrated-guide-to-lstms-and-gru-s-a-step-by-step-explanation-44e9eb85bf21"&gt;this useful link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Output layer: It has as many units as the size of the vocabulary&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The model definition code:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Length of the vocabulary in words
&lt;/span&gt;&lt;span class="n"&gt;vocab_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# The embedding dimension
&lt;/span&gt;&lt;span class="n"&gt;embedding_dim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;
&lt;span class="c1"&gt;# Number of GRU units
&lt;/span&gt;&lt;span class="n"&gt;rnn_units&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;createModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embedding_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rnn_units&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sequential&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Embedding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embedding_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                              &lt;span class="n"&gt;batch_input_shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
    &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GRU&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rnn_units&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;return_sequences&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;stateful&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;recurrent_initializer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'glorot_uniform'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dense&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;])&lt;/span&gt;
 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;embedding_dim&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;embedding_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rnn_units&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;rnn_units&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;BATCH_SIZE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  How the RNN works
&lt;/h1&gt;

&lt;p&gt;For each word in the input layer, the model passes its embedding to the GRU layer for one step of time. &lt;br&gt;
The output of the GRU is then passed to the dense layer which predicts the log-likelihood of the next word.&lt;/p&gt;

&lt;p&gt;The schematic below is a bit more descriptive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z_vLRp4Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ohb3xmbnf9v3qszc02o1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z_vLRp4Q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ohb3xmbnf9v3qszc02o1.png" alt="RNN Schematic" width="880" height="739"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Training the model
&lt;/h1&gt;

&lt;p&gt;From now on, we can consider the problem as a simple classification problem.&lt;br&gt;
If you think about it, our model predicts the "class" of the next word based on its current state and the input words during a time step.&lt;/p&gt;

&lt;p&gt;So, as in every classification model, in order to train it we need to calculate the loss in each time step.&lt;/p&gt;

&lt;p&gt;We do so by defining the following function:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;losses&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sparse_categorical_crossentropy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;labels&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;from_logits&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then we compile the model using 'adam' oprimizer.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;optimizer&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'adam'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;loss&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;During the training process, we should save checkpoints of the training in a directory that we have manually created&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;checkpoint_dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;'./training_checkpoints'&lt;/span&gt;
&lt;span class="n"&gt;checkpoint_prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;checkpoint_dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"ckpt_{epoch}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;checkpoint_callback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keras&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModelCheckpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;filepath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;checkpoint_prefix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;save_weights_only&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now it is time to execute training. &lt;br&gt;
We explicitly set the number of epochs. &lt;br&gt;
At this point I would like to remind you that an epoch is one forward pass and one backward pass of all the training examples.&lt;/p&gt;

&lt;p&gt;We choose to train for 20 epochs. Note that as you increase number of epochs, the training time will increase too.&lt;br&gt;
You should experiment with this number in order to fine tune the model. &lt;br&gt;
But be careful, training for too many epochs may lead to overfitting.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;EPOCHS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;epochs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;EPOCHS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;checkpoint_callback&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;After the training process is over, we restore the trained model form the latest checkpoint. &lt;br&gt;
It is time to generate the lyrics!&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;latest_checkpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;checkpoint_dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vocab&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;embedding_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rnn_units&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batch_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load_weights&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;train&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;latest_checkpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;checkpoint_dir&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TensorShape&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Generating the lyrics
&lt;/h1&gt;

&lt;p&gt;RNNs (as most of Neural network types in general) need an initial state to start predicting.&lt;br&gt;
In our case, this initialization is represented by a starting string with which we want the generated lyrics to start.&lt;br&gt;
The model generates the probability distribution of the next word using the start string and the RNN state.&lt;/p&gt;

&lt;p&gt;Then, with the help of categorical distribution, the index of the predicted word is calculated &lt;strong&gt;and the predicted word is used as the input for the next time step of the model&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The state that the RNN returns is then fed back to the input of the RNN, in order to help it by providing more context (not just one word). This process continues as it generates predictions and this is why it learns better while it gets more context from the predicted words.&lt;/p&gt;

&lt;p&gt;The following function performs the task mentioned above:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generateLyrics&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;startString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"---- Generating lyrics starting with '"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;startString&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"' ----"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="c1"&gt;# Number of words to generate
&lt;/span&gt;  &lt;span class="n"&gt;num_generate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;

  &lt;span class="c1"&gt;# Converting our start string to numbers (vectorizing)
&lt;/span&gt;  &lt;span class="n"&gt;start_string_list&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;startString&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
  &lt;span class="n"&gt;input_eval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;word2idx&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;start_string_list&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="n"&gt;input_eval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expand_dims&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_eval&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="n"&gt;text_generated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

  &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reset_states&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_generate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
      &lt;span class="n"&gt;predictions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_eval&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;# remove the batch dimension
&lt;/span&gt;      &lt;span class="n"&gt;predictions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;squeeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;predictions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;# temp represent how 'conservative' the predictions are. 
&lt;/span&gt;      &lt;span class="c1"&gt;# Lower temp leads to more predictable (or correct) lyrics
&lt;/span&gt;      &lt;span class="n"&gt;predictions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;predictions&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; 
      &lt;span class="n"&gt;predicted_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;categorical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;predictions&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_samples&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;numpy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

      &lt;span class="c1"&gt;# We pass the predicted word as the next input to the model
&lt;/span&gt;      &lt;span class="c1"&gt;# along with the previous hidden state
&lt;/span&gt;      &lt;span class="n"&gt;input_eval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expand_dims&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;predicted_id&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;text_generated&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;' '&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;idx2words&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;predicted_id&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;startString&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;''&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text_generated&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As you can see, many factors may influence the accuracy of the predictions.&lt;br&gt;
&lt;code&gt;temp&lt;/code&gt; parameter for example represents how 'conservative' the predictions are. &lt;br&gt;
This means that lower temp values lead to more predictable (or correct) lyrics.&lt;/p&gt;
&lt;h1&gt;
  
  
  Running the model
&lt;/h1&gt;

&lt;p&gt;model.py also contains a "demo part". &lt;br&gt;
After the training process is finished, it saves the model in a binary file (you can then restore it in one line of code and use it instantly to predict values) for future use so we do not have to train it every time we want to generate lyrics.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#save trained model for future use (so we do not have to train it every time we want to generate text)
&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'saved_model.h5'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then it calls the &lt;code&gt;generateLyrics&lt;/code&gt; function with the start string "love" (We all know how much Beatles used) this word in their songs.&lt;br&gt;
Then it prompts the user to enter a start string and a temp value to generate lyrics.&lt;/p&gt;

&lt;p&gt;Some examples that the model gave me:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start string: "love"
Generated lyrics: "love youyouyouyou as i write this letter send my love to give you all my loving i will send to you all my loving i will send to you don't bother"

Start string: "boys and girls"
temp: 0.4
Generated lyrics: "boys and girls make me sing and shout that georgia's always be blind love is here to stay and that's enough to make you my girl be the only one love me hold"

Start string: "day"
temp: 0.8
Generated lyrics: "day tripper night at my own it will take a walk on home loretta get back get back get back get back get back get back get back get back get"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
`&lt;br&gt;
Hm... Not that bad.&lt;/p&gt;
&lt;h1&gt;
  
  
  Optimizing the model
&lt;/h1&gt;

&lt;p&gt;You can easily fine-tune the model by changing the variables that influence the accuracy of the predictions. Using a stopwords set with the very common words in the corpus and removing them from the training data may help the predictions as it will eliminate the noise and the features that do not offer a significant info gain.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;BATCH_SIZE&lt;/code&gt;, &lt;code&gt;temp&lt;/code&gt;, embedding dimensions, sequence length can all influence the prediction and thus the generated lyrics.&lt;br&gt;
You can also try to use LSTM units in the middle layer.&lt;br&gt;
So you can experiment yourself and comment with the results.&lt;/p&gt;

&lt;p&gt;Project is available on this Github Repo&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/petrosDemetrakopoulos"&gt;
        petrosDemetrakopoulos
      &lt;/a&gt; / &lt;a href="https://github.com/petrosDemetrakopoulos/RNN-Beatles-lyrics-generator"&gt;
        RNN-Beatles-lyrics-generator
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
       A word-based Recurrent neural network (RNN) trained to generate Beatle-like lyrics
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>python</category>
      <category>machinelearning</category>
      <category>ai</category>
      <category>tensorflow</category>
    </item>
    <item>
      <title>SIR.js . An epidemic simulation library in JS.</title>
      <dc:creator>Petros Demetrakopoulos</dc:creator>
      <pubDate>Sun, 29 Mar 2020 16:53:33 +0000</pubDate>
      <link>https://dev.to/demetrakopetros/sir-js-an-epidemic-simulation-library-in-js-41j9</link>
      <guid>https://dev.to/demetrakopetros/sir-js-an-epidemic-simulation-library-in-js-41j9</guid>
      <description>&lt;p&gt;During the last days, I see more and more projects related to epidemic simulations, SIR Modeling etc. It is obvious that the COVID-19 pandemic has motivated developers around the world to offer projects and solutions that try to predict the evolution of the pandemic in the following weeks or months.&lt;/p&gt;

&lt;p&gt;Probably the simplest model someone can use to model an epidemic is the SIR model.&lt;/p&gt;

&lt;h1&gt;
  
  
  But how is the SIR model defined?
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;(From WolframMathworld)&lt;br&gt;
An SIR model is an epidemiological model that computes the theoretical number of people infected with a contagious illness in a closed population over time. The name of this class of models derives from the fact that they involve coupled equations relating the number of susceptible people &lt;strong&gt;S(t)&lt;/strong&gt;, number of people infected &lt;strong&gt;I(t)&lt;/strong&gt;, and number of people who have recovered &lt;strong&gt;R(t)&lt;/strong&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The model needs the initial values of the Susceptible persons in a population &lt;strong&gt;(S0)&lt;/strong&gt;, Infected &lt;strong&gt;(I0)&lt;/strong&gt; and Recovered &lt;strong&gt;(R0)&lt;/strong&gt;. It also needs &lt;strong&gt;beta&lt;/strong&gt; factor which is a constant determining how often a susceptible-infected contact results in a new infection and &lt;strong&gt;gamma&lt;/strong&gt; factor which is the rate an infected person recovers and moves into the resistant phase.&lt;/p&gt;

&lt;p&gt;The simulation runs for &lt;strong&gt;N&lt;/strong&gt; iterations (which represent the time span of the simulation).&lt;/p&gt;

&lt;h1&gt;
  
  
  Installation and example
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/sir.js"&gt;SIR.js&lt;/a&gt; can be installed via npm by typing &lt;code&gt;npm install sir.js&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;Code is available in this &lt;a href="https://github.com/petrosDemetrakopoulos/SIR.js"&gt;GitHub repo&lt;/a&gt; and you are welcome to contribute!&lt;/p&gt;

&lt;p&gt;It is ultrasimple to set it up and use it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;SIRjs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sir.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;solution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SIRjs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;solve&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;S0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;I0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;R0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;t&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;beta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;gamma&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;SIRjs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;printChart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;solution&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It has only 2 functions: &lt;code&gt;solve()&lt;/code&gt; and &lt;code&gt;printChart()&lt;/code&gt;&lt;br&gt;
&lt;code&gt;solve()&lt;/code&gt; function takes an object argument with the following keys:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;S0: Initial S (Susceptible) value&lt;/li&gt;
&lt;li&gt;I0: Initial I (Infectious) value&lt;/li&gt;
&lt;li&gt;R0: Initial R (Recovered) value&lt;/li&gt;
&lt;li&gt;t: The time step&lt;/li&gt;
&lt;li&gt;N: The time span (in units of time) aka the length of the simulation&lt;/li&gt;
&lt;li&gt;beta: The parameter controlling how often a susceptible-infected contact results in a new infection&lt;/li&gt;
&lt;li&gt;gamma: The rate an infected recovers and moves into the resistant phase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It returns an array of objects that contain S,I and R values for each moment.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;printChart()&lt;/code&gt; function prints an ASCII chart for each one of the S,I,R variables&lt;/p&gt;

&lt;p&gt;You can then plot the results in any way you want.&lt;br&gt;
Here, for example, I have plotted the results using Google Sheets&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UvHEyxWt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/24u7xu4k8kcw26chubf4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UvHEyxWt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/24u7xu4k8kcw26chubf4.png" alt="SIR Chart" width="843" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  That's all folks!
&lt;/h1&gt;

&lt;p&gt;I hope you find it interesting and that it will be useful!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>opensource</category>
      <category>simulation</category>
    </item>
    <item>
      <title>COVID-19: An opportunity for the developers’ community and Open Source Software.</title>
      <dc:creator>Petros Demetrakopoulos</dc:creator>
      <pubDate>Sun, 15 Mar 2020 19:25:07 +0000</pubDate>
      <link>https://dev.to/demetrakopetros/covid-19-an-opportunity-for-the-developers-community-and-open-source-software-437g</link>
      <guid>https://dev.to/demetrakopetros/covid-19-an-opportunity-for-the-developers-community-and-open-source-software-437g</guid>
      <description>&lt;p&gt;Facts: COVID-19 is already a global pandemic. Many software developers and ICT professionals in general have already turned to work-from-home mode as the official guideline is to STAY HOME.&lt;/p&gt;

&lt;p&gt;Most developers are really passionate about their job and as a result they have a really strong community that is the moving force of the software evolution. I am also pretty sure that for most developers it will be really difficult to watch tons of series and films on Netflix during the hard days of quarantine. Sooner or later they will have the need to code during their spare time in their homes.&lt;/p&gt;

&lt;p&gt;So here are a few things (many are obvious) we can do to make the days we will pass much more time in our homes count and offer more to our community.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Learn a new programming language/technology or framework.&lt;br&gt;
By watching youtube videos, taking courses in Udemy / Coursera / edx etc. You know the ways are infinite.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Answer questions in StackOverflow and other community forums.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Start this side-project that you always wanted to and you could not find time to do it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Write tests for your existing projects (if you have not done it already). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The most important one: Contribute to Open Source projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There are millions of open source projects out there. Find the one you like or you use in your projects, visit its repository on GitHub, check the open issues, try to resolve one and then make a pull request. I am sure that you will learn many things during the process.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;The time you will have to spend staying at home is a lot. Try not to waste it and spend it as creatively as you can while offering to the community too.&lt;/p&gt;

&lt;p&gt;So what do you think? What other opportunities emerge in the community due to COVID-19? Feel free to discuss in the comment section.&lt;/p&gt;

&lt;p&gt;Stay Safe,&lt;br&gt;
 #StayHome ,&lt;br&gt;
 And keep coding : )&lt;/p&gt;

</description>
      <category>motivation</category>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Using data models over Ethereum blockchain with EthAir Balloons</title>
      <dc:creator>Petros Demetrakopoulos</dc:creator>
      <pubDate>Mon, 03 Feb 2020 10:57:59 +0000</pubDate>
      <link>https://dev.to/demetrakopetros/using-data-models-over-ethereum-blockchain-using-ethair-balloons-50e9</link>
      <guid>https://dev.to/demetrakopetros/using-data-models-over-ethereum-blockchain-using-ethair-balloons-50e9</guid>
      <description>&lt;p&gt;Back to basics:&lt;br&gt;
First of all, let's remember what blockchains are: A blockchain in Layman's terms is a kind of &lt;em&gt;distributed database that offers more transparency and more security&lt;/em&gt; than other databases. This means that their main role is to &lt;strong&gt;store data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ethereum blockchain is amazing because it was the first to offer the capability of running code over it with Smart contracts and Solidity, the language behind them. But Solidity smart contracts may be a real hell even for experienced developers as their development is very time consuming, they cannot be easily tested and they have many limitations such as not many available data types, the limited number of parameters you can pass into a function, lack of object-oriented concepts, etc. It feels more like a very primitive programming language than a modern one that allows more complex data structures and functions.&lt;/p&gt;

&lt;p&gt;And here comes &lt;a href="https://github.com/petrosDemetrakopoulos/ethairballoons"&gt;EthAir Balloons&lt;/a&gt;, a spin-off project of my thesis as an undergraduate student in CS School of Athens University of Economics and Business.&lt;/p&gt;

&lt;p&gt;EthAir Balloons is a strictly typed ORM library for Ethereum blockchain. It allows you to use Ethereum blockchain as persistent storage in an organized and model-oriented way &lt;strong&gt;without writing custom complex Smart contracts&lt;/strong&gt;. We could tell it is for Ethereum based blockchains what Mongoose is for MongoDB.&lt;/p&gt;

&lt;p&gt;We will do a walkthrough to the library by showing how you can very easily  create and deploy a new model and then perform all the CRUD operations.&lt;/p&gt;

&lt;p&gt;Assuming we have already created a new Node.js project and an &lt;code&gt;index.js&lt;/code&gt; file, we can proceed to the installation of the library by typing &lt;code&gt;npm i --save ethairballoons&lt;/code&gt; in the root directory of the project.&lt;/p&gt;

&lt;p&gt;Now, in the index.js file we add the following lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ethAirBalloons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ethairballoons&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;savePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/contracts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;ethAirBalloonsProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethAirBalloons&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:8545&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;savePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;span class="c1"&gt;//ethereum blockchain provider URL, path to save auto generated smart contracts&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;Car&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ethAirBalloonsProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createSchema&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Car&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;contractName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;carsContract&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;model&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bytes32&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; 
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;engine&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bytes32&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;   &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cylinders&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;uint&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we can initiate an instance of &lt;code&gt;ethairballoons&lt;/code&gt; (or what I like to call an "ethAirBalloons provider") using only 2 arguments:&lt;/p&gt;

&lt;p&gt;1) the URL of the Ethereum blockchain provider that we want to use (in the example it is set to a local ganache-cli provider),&lt;/p&gt;

&lt;p&gt;2) the path where we want to save the automatically generated smart contracts of your models.&lt;/p&gt;

&lt;p&gt;After the provider initialisation, we can create new data schemas using the &lt;code&gt;createSchema()&lt;/code&gt; function and pass the schema details in JS object format. Of course you can (an it is advised) keep the schema definitions in separate .JSON files and then import them using the &lt;code&gt;require()&lt;/code&gt; statement in the top of your file.&lt;/p&gt;

&lt;p&gt;Now that our data schema is set, it is time to deploy it in the blockchain, in this point I would like to rememeber that we do so in a local &lt;code&gt;ganache-cli&lt;/code&gt; instance (which is an Ethereum blockchain simulator) and not in the actual ethereum network. &lt;strong&gt;As transaction fees may be huge, it is strongly advised to only deploy EthAir Balloons models in private Ethereum blockchains or locally using &lt;code&gt;ganache-cli&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We deploy our model by calling the &lt;code&gt;deploy()&lt;/code&gt; function as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Deployed successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function generates the solidity Smart contract of our model and deploys it in the Ethereum based blockchain that we set in the previous step. It returns a boolean indicating if the deploy is successfull and an error object that will be undefined if the deploy is successfull. After deploy completes wecan call the other functions of the model.&lt;/p&gt;

&lt;h1&gt;
  
  
  Model functions
&lt;/h1&gt;

&lt;p&gt;EthAir Balloons implement all the functions needed to perform CRUD operations.&lt;/p&gt;

&lt;h3&gt;
  
  
  save()
&lt;/h3&gt;

&lt;p&gt;This function saves a new record in the blockchain. Make sure to set the primary key field in the object you want to save, otherwise an error will be returned. It returns the saved object and an error object that will be undefined if the object is saved successfully.&lt;/p&gt;

&lt;p&gt;An example is shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;newCarObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Audi A4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;V8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;wheels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newCarObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;objectSaved&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object saved&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  find()
&lt;/h3&gt;

&lt;p&gt;This function returns all the records of our Model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;allRecords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;allRecords&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  findById()
&lt;/h3&gt;

&lt;p&gt;This function returns the record with a specific primary key value if exists. Otherwise it will return an error object mentioning that 'record with this id does not exist'.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;findById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Audi A4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;record&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  deleteById()
&lt;/h3&gt;

&lt;p&gt;Deletes the record with a specific primary key value if exists. Otherwise it will return an error object mentioning that 'record with this id does not exist'.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deleteById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Audi A4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object deleted successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  updateById()
&lt;/h3&gt;

&lt;p&gt;Updates the record with a specific primary key value if exists. Otherwise it will return an error object mentioning that 'record with this id does not exist'. It returns the updated record.&lt;/p&gt;

&lt;p&gt;The first parameter is the primary key value of the record we want to update. The second parameter is the updated object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;updatedCarObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;V9&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;wheels&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Audi A4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;updatedCarObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedObject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;object updated successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  That's all folks!
&lt;/h2&gt;

&lt;p&gt;I hope you find it interesting and that it will be useful in future projects!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>crypto</category>
      <category>ethereum</category>
      <category>blockchain</category>
    </item>
  </channel>
</rss>
