<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Overfitting - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Overfitting - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 26 Jul 2026 22:34:13 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/overfitting/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ What is Overfitting in Machine Learning? ]]>
                </title>
                <description>
                    <![CDATA[ Have you ever performed some task without really thinking about the process involved? For example, making coffee, tying your shoes, or walking through your neighborhood.  In these types of activities, you've done these things so many times that you'v... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/what-is-overfitting-machine-learning/</link>
                <guid isPermaLink="false">66c71f7acdd5b7ce3d9c37da</guid>
                
                    <category>
                        <![CDATA[ Artificial Intelligence ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Machine Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Overfitting ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Mene-Ejegi Ogbemi ]]>
                </dc:creator>
                <pubDate>Mon, 16 Oct 2023 20:21:22 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/09/Banner---Tech-writing---Overfitting.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Have you ever performed some task without really thinking about the process involved? For example, making coffee, tying your shoes, or walking through your neighborhood. </p>
<p>In these types of activities, you've done these things so many times that you've mastered the process. You can be thinking about something unrelated, yet you perform these activities all the same. This phenomenon is called procedural memory in psychology.</p>
<p>We have this kind of thing with machine learning models as well, but it's not as positive as it is with humans. This is known as overfitting in machine learning. </p>
<h2 id="heading-what-is-overfitting">What is Overfitting?</h2>
<p>In overfitting, a model becomes so good at our training data that it has mastered every pattern, including noise. This makes the model perform well with training data but poorly with test or validation data.</p>
<p>The illustration below depicts how an optimal model fits into the data compared to overfitting. </p>
<p>In the graph, we have our features on the x-axis. In datasets, features are data that can be used to predict an outcome. The output variable is the outcome based on those features. The blue dots represent the data points where the features determine output variables. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/overfitting-illustration.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the optimal graph, our model tries to find the generalized trend. But in our overfitted chart, the model tries to master each data point, resulting in an asymmetrical curve.</p>
<p>An example of a case study would be to predict if a customer would default on a bank loan. Assuming we have a dataset of 100,000 customers containing features such as demographics, income, loan amount, credit history, employment record, and default status, we split our data into training and test data. </p>
<p>Our training dataset contains 80,000 customers, while our test dataset contains 20,000 customers. In the training the dataset, we observe that our model has a 97% accuracy, but in prediction, we only get 50% accuracy. This shows that we have an overfitting problem.</p>
<p>Can you tell why overfitting is a problem? Yes! It produces an incorrect prediction. It is the purpose of machine learning models to make predictions to help business decision-making. We waste time and resources when our model makes incorrect predictions. </p>
<p>Imagine predicting that a customer will pay back a loan, and the customer defaults. Not just one customer but thousands of customers. This can cause a crisis for any financial institution.</p>
<h2 id="heading-causes-of-overfitting">Causes of Overfitting</h2>
<h3 id="heading-noisy-data">Noisy data</h3>
<p>Noise in data often appears as errors, fluctuations, or outliers in the data. This can be caused by data entry errors, data aging, data transmission errors, and so on. </p>
<p>Too much noise in data can cause the model to think these are valid data points. Fitting the noise pattern in the training dataset will cause poor performance on the new dataset.  </p>
<p>For example, let's say that we are building a machine-learning model to classify images of cats and dogs. But some of the images in the dataset are blurry or poorly lit. While the model may perform well on the training data, it might struggle on the test data since it must have mastered some pattern with the blurry images in the dataset.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/Cat-and-dog-3.jpg" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the picture above, you can see that we have some blurry images that cannot be labelled if they are cat or dog. In these instances, the model could also learn these patterns alongside relevant features. Removing these images can reduce overfitting.</p>
<h3 id="heading-insufficient-training-data">Insufficient training data</h3>
<p>There will be fewer patterns and noises to analyze if we don't have sufficient training data. This means that the machine can only learn a little about our data. </p>
<p>Using our previous example, if our training data contains fewer images of dogs but many more of cats, the model learns so much about cats that when we feed the system an image of a dog, it will likely give a wrong output.</p>
<h3 id="heading-overly-complex-model">Overly complex model</h3>
<p>In a complex model, there are many parameters capable of capturing patterns and relationships in training data. As a result, our model makes a more accurate prediction. </p>
<p>But this can pose a problem, since the model can start capturing noise, fluctuations, or outliers. Let's look at a decision tree model, how it works, and how overfitting can happen when it becomes too complex.</p>
<p>A decision tree model works by repeatedly breaking down data into significant features, making each point a node. This creates a tree like structure. </p>
<p>To make a prediction, it starts from the root node and follow the branches down, breaking and fitting every feature until it gets to the leaf node. The prediction is then made based on the value associated with the leaf node.</p>
<p>Let's look at a simple tree diagram of how a decision tree can predict if a customer is likely to default on loan base on certain features.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/decision-tree-flowchart.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tree diagram showing whether a customer is likely to default on a loan</em></p>
<p>This model starts by creating a parent node which is credit score. Depending on whether the credit score for the applicant is high or low, it goes down to the next node, which is either debt to income ratio or employment status. Then it makes the final prediction as to whether the customer is likely to default or not.</p>
<p>A decision tree can become overly complex when it creates too many nodes, making it too detailed or specific to the training data. </p>
<p>Let's see a sample machine learning program that predicts whether a customer will default a loan or not using decision tree model. For specificity, I wont be showing the cleaning process and visualization. I'll just lay emphasis on the required functions and how overfitting can happen with decision tree model. </p>
<p>The link to the complete repository containing cleaning and visualization can be found <a target="_blank" href="https://github.com/ogbemi-ejegi/Overfitting">here</a>, and you can get the dataset <a target="_blank" href="https://www.kaggle.com/datasets/rishikeshkonapure/home-loan-approval?select=loan_sanction_train.csv">here</a>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">from</span> sklearn.metrics <span class="hljs-keyword">import</span> accuracy_score
<span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split
<span class="hljs-keyword">from</span> sklearn.preprocessing <span class="hljs-keyword">import</span> LabelEncoder
<span class="hljs-keyword">from</span> sklearn <span class="hljs-keyword">import</span> tree
<span class="hljs-keyword">from</span> sklearn <span class="hljs-keyword">import</span> metrics
<span class="hljs-keyword">from</span> sklearn.tree <span class="hljs-keyword">import</span> DecisionTreeClassifier

%matplotlib inline

<span class="hljs-comment">#Importing our libraries</span>
train = pd.read_csv(<span class="hljs-string">'/content/train.csv'</span>)
test = pd.read_csv(<span class="hljs-string">'/content/test.csv'</span>)

<span class="hljs-comment">#Combine both training and test data</span>
df = pd.concat([train, test], axis=<span class="hljs-number">0</span>)
df.head()

<span class="hljs-comment">#View dataset</span>
train.head()

<span class="hljs-comment"># Copy require features to a variable df_</span>
df_ = train[[<span class="hljs-string">'Gender'</span>,
<span class="hljs-string">'Married'</span>,
<span class="hljs-string">'Education'</span>,
<span class="hljs-string">'Self_Employed'</span>,
<span class="hljs-string">'Dependents'</span>,
<span class="hljs-string">'ApplicantIncome'</span>,
<span class="hljs-string">'CoapplicantIncome'</span>,
<span class="hljs-string">'LoanAmount'</span>,
<span class="hljs-string">'Loan_Amount_Term'</span>,
<span class="hljs-string">'Property_Area'</span>,
<span class="hljs-string">'Credit_History'</span>]]

<span class="hljs-comment">### Duplicate a copy of df into X</span>
X = df_.copy()

<span class="hljs-comment">### label encode for Y</span>
y = train[<span class="hljs-string">'Loan_Status'</span>].map({<span class="hljs-string">'N'</span>:<span class="hljs-number">0</span>,<span class="hljs-string">'Y'</span>:<span class="hljs-number">1</span>}).astype(int)

<span class="hljs-comment">### train-test split</span>
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=<span class="hljs-number">0.2</span>, random_state=<span class="hljs-number">42</span>)

<span class="hljs-comment"># train</span>
clf = DecisionTreeClassifier() <span class="hljs-comment">#change model here</span>
clf.fit(X_train, y_train)

<span class="hljs-comment"># predict</span>
predictions_clf = clf.predict(X_test)

<span class="hljs-comment">#Print Accuracy</span>
print(<span class="hljs-string">'Model Accuracy:'</span>, accuracy_score(predictions_clf, y_test))
</code></pre>
<p>To understand this better, I'll explain what each module does:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">from</span> sklearn.metrics <span class="hljs-keyword">import</span> accuracy_score
<span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split
<span class="hljs-keyword">from</span> sklearn.preprocessing <span class="hljs-keyword">import</span> LabelEncoder
<span class="hljs-keyword">from</span> sklearn <span class="hljs-keyword">import</span> tree
<span class="hljs-keyword">from</span> sklearn <span class="hljs-keyword">import</span> metrics
<span class="hljs-keyword">from</span> sklearn.tree <span class="hljs-keyword">import</span> DecisionTreeClassifier
</code></pre>
<p>The first block is the import section. This is where we import all our dependencies. </p>
<ul>
<li>Numpy is a Python library used for scientific computing. </li>
<li>Pandas is a library for data analysis and manipulation. </li>
<li>Matplotlib and Seaborn are for statistical data visualization. </li>
<li><code>Accuracy_score</code> is a function to calculate the accuracy of our model.</li>
<li><code>train_test_split</code> is used to split our dataset into training and test data. </li>
<li>The <code>LabelEncoder</code> encodes categorical variables into numeric variables. </li>
<li><code>tree</code> is for building a decision tree classifier. </li>
<li><code>metrics</code> helps us evaluate our models.</li>
</ul>
<pre><code class="lang-python"><span class="hljs-comment">#Importing our dataset</span>
train = pd.read_csv(<span class="hljs-string">'/content/train.csv'</span>)
test = pd.read_csv(<span class="hljs-string">'/content/test.csv'</span>)
</code></pre>
<p>This module imports our datasets. Our train and test datasets have been downloaded from the public repository, so we import them separately.</p>
<pre><code class="lang-python"><span class="hljs-comment">#Combine both training and test data</span>
df = pd.concat([train, test], axis=<span class="hljs-number">0</span>)
df.head()
</code></pre>
<p>To work with both datasets, we need to combine them into one dataset. The concat function combines both datasets. We use <code>df.head()</code> to visualize the dataset which is shown below.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-76.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot of our dataset</em></p>
<pre><code class="lang-python"><span class="hljs-comment"># Copy require features to a variable df_</span>
df_ = train[[<span class="hljs-string">'Gender'</span>,
<span class="hljs-string">'Married'</span>,
<span class="hljs-string">'Education'</span>,
<span class="hljs-string">'Self_Employed'</span>,
<span class="hljs-string">'Dependents'</span>,
<span class="hljs-string">'ApplicantIncome'</span>,
<span class="hljs-string">'CoapplicantIncome'</span>,
<span class="hljs-string">'LoanAmount'</span>,
<span class="hljs-string">'Loan_Amount_Term'</span>,
<span class="hljs-string">'Property_Area'</span>,
<span class="hljs-string">'Credit_History'</span>]]

<span class="hljs-comment">### Duplicate a copy of df into X</span>
X = df_.copy()
</code></pre>
<p>To start working with our features, we created a variable df_ to store all the features needed for prediction. We duplicated this into the variable X to create a copy to work with.</p>
<pre><code class="lang-python"><span class="hljs-comment">### label encode for Y</span>
y = train[<span class="hljs-string">'Loan_Status'</span>].map({<span class="hljs-string">'N'</span>:<span class="hljs-number">0</span>,<span class="hljs-string">'Y'</span>:<span class="hljs-number">1</span>}).astype(int)
</code></pre>
<p>To work with our outcome variable, we needed to convert it from a categorical value to an integer value. This also makes it easy for our model to understand. All values of N were converted to 0, while Y was converted to 1.</p>
<pre><code class="lang-python"><span class="hljs-comment">### train-test split</span>
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=<span class="hljs-number">0.2</span>, random_state=<span class="hljs-number">42</span>)
</code></pre>
<p>We use our <code>train_test_split</code> to split our data into training and test data. The <code>test_size = 0.2</code> means we are using 20% of the data for testing and 80% for training.</p>
<pre><code class="lang-python"><span class="hljs-comment"># train</span>
clf = DecisionTreeClassifier()
clf.fit(X_train, y_train)
</code></pre>
<p>We assigned <code>DecisionTreeClassifier()</code> to the variable <code>clf</code>, which we'll use to train and fit our data. <code>DecisionTreeClassifier()</code> has an optional argument named <code>max_depth</code>. The number assigned to <code>max_depth</code> determines the depth of the tree. This is how we'll use it to cause overfitting in another section below.</p>
<pre><code class="lang-python"><span class="hljs-comment"># predict</span>
predictions_clf = clf.predict(X_test)
</code></pre>
<p>In the code snippet above, <code>clf.predict</code> is used to predict the data in <code>X_test</code>. </p>
<pre><code class="lang-python">print(<span class="hljs-string">'Model Accuracy:'</span>, accuracy_score(predictions_clf, y_test))
</code></pre>
<p>The model accuracy was printed using the accuracy_score function, which you can see in the screenshot below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/image-77.png" alt="Image" width="600" height="400" loading="lazy">
<em>Model accuracy - almost 70%</em></p>
<p>Now that we've seen how a decision tree works and even run a machine learning model to predict if a customer will default or not, let's see how to cause and diagnose overfitting by modifying the code using the <code>max_depth</code> argument.</p>
<h2 id="heading-how-to-diagnose-overfitting">How to Diagnose Overfitting</h2>
<h3 id="heading-visualizations">Visualizations</h3>
<p>Using visualizations can help us detect overfitting by providing insights into the behavior of our model. </p>
<p>Common visualization methods include plotting data points for the model's prediction, visualizing feature distributions, or creating plots of decision boundaries. </p>
<p>To visualize the overfitting for our loan application above, I had to tweak the code by creating an iteration using different <code>max_depth</code> values ranging from 1 to 24. Predictions are calculated based on training and test data and stored in a list.</p>
<pre><code class="lang-python"><span class="hljs-comment">#Creating a list to store accuracy values</span>
train_accuracies = []
test_accuracies = []

<span class="hljs-comment">#Loop</span>
<span class="hljs-keyword">for</span> depth <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>, <span class="hljs-number">25</span>):
  tree_model = DecisionTreeClassifier(max_depth = depth)
  tree_model.fit(X_train, y_train)

  train_predictions = tree_model.predict(X_train)
  test_predictions = tree_model.predict(X_test)

  <span class="hljs-comment">#calculate training and test accuracy</span>
  train_accuracy = metrics.accuracy_score(y_train, train_predictions)

  test_accuracy = metrics.accuracy_score(y_test, test_predictions)

  <span class="hljs-comment">#Append accuracies</span>
  train_accuracies.append(train_accuracy)
  test_accuracies.append(test_accuracy)
</code></pre>
<p>The difference here is that we are creating two variables – <code>train_accuracies</code> and <code>test_accuracies</code> – to store the accuracy values. Using these variables, we can use the code below to generate a plot that shows the changes between these variables as the <code>max_depth</code> value changes.</p>
<pre><code class="lang-python"><span class="hljs-comment">#Creating our plot</span>
plt.figure(figsize = (<span class="hljs-number">10</span>, <span class="hljs-number">5</span>))
sns.set_style(<span class="hljs-string">"whitegrid"</span>)
plt.plot(train_accuracies, label= <span class="hljs-string">"train accuracy"</span>)
plt.plot(test_accuracies, label=<span class="hljs-string">"test accuracy"</span>)
plt.legend(loc = <span class="hljs-string">"upper left"</span>)
plt.xticks(range(<span class="hljs-number">0</span>, <span class="hljs-number">26</span>, <span class="hljs-number">5</span>))
plt.xlabel(<span class="hljs-string">"max_depth"</span>, size = <span class="hljs-number">20</span>)
plt.ylabel(<span class="hljs-string">"accuracy"</span>, size = <span class="hljs-number">20</span>)
plt.show()
</code></pre>
<p>This is how the plot looks:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/overfitting-visualization-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Train accuracy vs test accuracy</em></p>
<p>You'll notice that as <code>max_depth</code> values on the x-axis begin to increase, the training data accuracy starts improving a lot to a perfect score. In spite of this, the test data accuracy decreased from 0.78 to 0.70. This is a classic example of overfitting as the model becomes too complex.</p>
<h3 id="heading-training-and-validation-accuracy-gap">Training and validation accuracy gap</h3>
<p>The accuracy gap is a good way to know if overfitting has occurred in your program. This means that there is a wide gap between training data and validation data when it comes to accuracy. </p>
<p>As a guide, a 5% gap is what you should look for. Cases where you have more than this are often an indicator of overfitting: for example, our visualization above shows that when our <code>max_depth</code> value was at 2o, our training accuracy was at 100% while our test accuracy was 70%.</p>
<h2 id="heading-how-to-prevent-overfitting">How to Prevent Overfitting</h2>
<h3 id="heading-collect-more-training-data">Collect more training data</h3>
<p>As discussed above, insufficient training data can cause overfitting as the model cannot capture the relevant patterns and intricacies represented in the data. </p>
<p>Machine learning generally requires thousands or millions of records in your dataset for training. With this, there will be enough patterns to capture. You can identify outliers or noise more easily if you've done proper cleaning on the dataset using relevant techniques.</p>
<h3 id="heading-use-regularization-techniques">Use regularization techniques</h3>
<p>Regularization techniques involve simplifying models by penalizing less influential features. These penalties are embedded in the model's loss function.</p>
<p>Regularization techniques for the decision tree model above include pruning, cost complexity pruning, and others.</p>
<p>Pruning is a technique that involves removing unnecessary branches from the decision tree. For example, we can set a minimum number of customers on a leaf, such as 20. This prevents the tree from making decisions based on a very small group of customers.</p>
<p>Cost complexity involves removing branches from the tree based on their complexity. This controls the trade-off between tree complexity and accuracy.</p>
<h3 id="heading-ensembling">Ensembling</h3>
<p>Ensembling entails combining several machine learning models to contribute their strengths and unique perspectives to make a prediction. </p>
<p>Ensembling leverages the wisdom of the crowd to make more accurate predictions on unseen data, which improves generalization and reduces the risk of overfitting. </p>
<p>Popular ensemble methods include bagging, boosting, and stacking, which have been successful in a wide range of machine-learning tasks.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/10/ENSEMBLE-1.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Diagram showing how ensembling works</em></p>
<p>The diagram above shows how the ensembling method combines various machine learning models for making predictions. Each model is trained independently on its respective subset of data. The predictions for individual models are then combined or the mean is gotten to make a final prediction.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Overfitting happens when a model fits training data too closely, resulting in great training performance but poor generalization. Overfitting can be problematic as it yields incorrect predictions.</p>
<p>This can be caused by a lack of training data, an overly complex model, or noisy data. Diagnosis involves assessing the training-validation accuracy gap, using visualizations to scrutinize model behavior, and so on.</p>
<p>Prevention strategies include collecting more training data, using regularization techniques, and employing ensemble methods. These approaches ensure models generalize well and make accurate predictions for informed decisions.</p>
<p>Thank you for reading! Please follow me on <a target="_blank" href="https://www.linkedin.com/in/ogbemi-ejegi/">LinkedIn</a> where I also post more data related content.</p>
<h4 id="heading-references">References:</h4>
<ul>
<li>Siddhardhan. "Overfitting in Machine Learning | Causes for Overfitting and its Prevention" [Video]. Retrieved from <a target="_blank" href="https://www.youtube.com/watch?v=gy8kXdd6K-o">https://www.youtube.com/watch?v=gy8kXdd6K-o</a></li>
<li>Udacity. "Ensemble Learners" [Video]. Retrieved from <a target="_blank" href="https://www.youtube.com/watch?v=Un9zObFjBH0">https://www.youtube.com/watch?v=Un9zObFjBH0</a></li>
<li>White Board Machine Learning. "Overfitting in Decision Trees" [Video]. Retrieved from <a target="_blank" href="https://www.youtube.com/watch?v=eU4X-dL8nYo">https://www.youtube.com/watch?v=eU4X-dL8nYo</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Handle Overfitting in Deep Learning Models ]]>
                </title>
                <description>
                    <![CDATA[ By Bert Carremans Overfitting occurs when you achieve a good fit of your model on the training data, but it does not generalize well on new, unseen data. In other words, the model learned patterns specific to the training data, which are irrelevant i... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/handling-overfitting-in-deep-learning-models/</link>
                <guid isPermaLink="false">66d45dd9bc9760a197a10351</guid>
                
                    <category>
                        <![CDATA[ Deep Learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ keras ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Overfitting ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                    <category>
                        <![CDATA[ regularization ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Sun, 05 Jan 2020 22:36:48 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/01/1_XXtWMdH-YVL8z1VtnfG_iw.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Bert Carremans</p>
<p>Overfitting occurs when you achieve a good fit of your model on the training data, but it does not generalize well on new, unseen data. In other words, the model learned patterns specific to the training data, which are irrelevant in other data.</p>
<p>We can identify overfitting by looking at validation metrics like loss or accuracy. Usually, the validation metric stops improving after a certain number of epochs and begins to decrease afterward. The training metric continues to improve because the model seeks to find the best fit for the training data.</p>
<p>There are several manners in which we can reduce overfitting in deep learning models. The best option is to <strong>get more training data</strong>. Unfortunately, in real-world situations, you often do not have this possibility due to time, budget, or technical constraints.</p>
<p>Another way to reduce overfitting is to <strong>lower the capacity of the model to memorize the training data</strong>. As such, the model will need to focus on the relevant patterns in the training data, which results in better generalization. In this post, we’ll discuss three options to achieve this.</p>
<h1 id="heading-set-up-the-project">Set up the project</h1>
<p>We start by importing the necessary packages and configuring some parameters. We will use <a target="_blank" href="https://keras.io/">Keras</a> to fit the deep learning models. The training data is the <a target="_blank" href="https://www.kaggle.com/crowdflower/twitter-airline-sentiment">Twitter US Airline Sentiment data set from Kaggle</a>.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Basic packages</span>
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd 
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> re
<span class="hljs-keyword">import</span> collections
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">from</span> pathlib <span class="hljs-keyword">import</span> Path
<span class="hljs-comment"># Packages for data preparation</span>
<span class="hljs-keyword">from</span> sklearn.model_selection <span class="hljs-keyword">import</span> train_test_split
<span class="hljs-keyword">from</span> nltk.corpus <span class="hljs-keyword">import</span> stopwords
<span class="hljs-keyword">from</span> keras.preprocessing.text <span class="hljs-keyword">import</span> Tokenizer
<span class="hljs-keyword">from</span> keras.utils.np_utils <span class="hljs-keyword">import</span> to_categorical
<span class="hljs-keyword">from</span> sklearn.preprocessing <span class="hljs-keyword">import</span> LabelEncoder
<span class="hljs-comment"># Packages for modeling</span>
<span class="hljs-keyword">from</span> keras <span class="hljs-keyword">import</span> models
<span class="hljs-keyword">from</span> keras <span class="hljs-keyword">import</span> layers
<span class="hljs-keyword">from</span> keras <span class="hljs-keyword">import</span> regularizers
NB_WORDS = <span class="hljs-number">10000</span>  <span class="hljs-comment"># Parameter indicating the number of words we'll put in the dictionary</span>
NB_START_EPOCHS = <span class="hljs-number">20</span>  <span class="hljs-comment"># Number of epochs we usually start to train with</span>
BATCH_SIZE = <span class="hljs-number">512</span>  <span class="hljs-comment"># Size of the batches used in the mini-batch gradient descent</span>
MAX_LEN = <span class="hljs-number">20</span>  <span class="hljs-comment"># Maximum number of words in a sequence</span>
root = Path(<span class="hljs-string">'../'</span>)
input_path = root / <span class="hljs-string">'input/'</span> 
ouput_path = root / <span class="hljs-string">'output/'</span>
source_path = root / <span class="hljs-string">'source/'</span>
</code></pre>
<h1 id="heading-some-helper-functions">Some helper functions</h1>
<p>We will use some helper functions throughout this post.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">deep_model</span>(<span class="hljs-params">model, X_train, y_train, X_valid, y_valid</span>):</span>
    <span class="hljs-string">'''
    Function to train a multi-class model. The number of epochs and 
    batch_size are set by the constants at the top of the
    notebook. 

    Parameters:
        model : model with the chosen architecture
        X_train : training features
        y_train : training target
        X_valid : validation features
        Y_valid : validation target
    Output:
        model training history
    '''</span>
    model.compile(optimizer=<span class="hljs-string">'rmsprop'</span>
                  , loss=<span class="hljs-string">'categorical_crossentropy'</span>
                  , metrics=[<span class="hljs-string">'accuracy'</span>])

    history = model.fit(X_train
                       , y_train
                       , epochs=NB_START_EPOCHS
                       , batch_size=BATCH_SIZE
                       , validation_data=(X_valid, y_valid)
                       , verbose=<span class="hljs-number">0</span>)
    <span class="hljs-keyword">return</span> history
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">eval_metric</span>(<span class="hljs-params">model, history, metric_name</span>):</span>
    <span class="hljs-string">'''
    Function to evaluate a trained model on a chosen metric. 
    Training and validation metric are plotted in a
    line chart for each epoch.

    Parameters:
        history : model training history
        metric_name : loss or accuracy
    Output:
        line chart with epochs of x-axis and metric on
        y-axis
    '''</span>
    metric = history.history[metric_name]
    val_metric = history.history[<span class="hljs-string">'val_'</span> + metric_name]
    e = range(<span class="hljs-number">1</span>, NB_START_EPOCHS + <span class="hljs-number">1</span>)
    plt.plot(e, metric, <span class="hljs-string">'bo'</span>, label=<span class="hljs-string">'Train '</span> + metric_name)
    plt.plot(e, val_metric, <span class="hljs-string">'b'</span>, label=<span class="hljs-string">'Validation '</span> + metric_name)
    plt.xlabel(<span class="hljs-string">'Epoch number'</span>)
    plt.ylabel(metric_name)
    plt.title(<span class="hljs-string">'Comparing training and validation '</span> + metric_name + <span class="hljs-string">' for '</span> + model.name)
    plt.legend()
    plt.show()
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_model</span>(<span class="hljs-params">model, X_train, y_train, X_test, y_test, epoch_stop</span>):</span>
    <span class="hljs-string">'''
    Function to test the model on new data after training it
    on the full training data with the optimal number of epochs.

    Parameters:
        model : trained model
        X_train : training features
        y_train : training target
        X_test : test features
        y_test : test target
        epochs : optimal number of epochs
    Output:
        test accuracy and test loss
    '''</span>
    model.fit(X_train
              , y_train
              , epochs=epoch_stop
              , batch_size=BATCH_SIZE
              , verbose=<span class="hljs-number">0</span>)
    results = model.evaluate(X_test, y_test)
    print()
    print(<span class="hljs-string">'Test accuracy: {0:.2f}%'</span>.format(results[<span class="hljs-number">1</span>]*<span class="hljs-number">100</span>))
    <span class="hljs-keyword">return</span> results

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">remove_stopwords</span>(<span class="hljs-params">input_text</span>):</span>
    <span class="hljs-string">'''
    Function to remove English stopwords from a Pandas Series.

    Parameters:
        input_text : text to clean
    Output:
        cleaned Pandas Series 
    '''</span>
    stopwords_list = stopwords.words(<span class="hljs-string">'english'</span>)
    <span class="hljs-comment"># Some words which might indicate a certain sentiment are kept via a whitelist</span>
    whitelist = [<span class="hljs-string">"n't"</span>, <span class="hljs-string">"not"</span>, <span class="hljs-string">"no"</span>]
    words = input_text.split() 
    clean_words = [word <span class="hljs-keyword">for</span> word <span class="hljs-keyword">in</span> words <span class="hljs-keyword">if</span> (word <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> stopwords_list <span class="hljs-keyword">or</span> word <span class="hljs-keyword">in</span> whitelist) <span class="hljs-keyword">and</span> len(word) &gt; <span class="hljs-number">1</span>] 
    <span class="hljs-keyword">return</span> <span class="hljs-string">" "</span>.join(clean_words) 

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">remove_mentions</span>(<span class="hljs-params">input_text</span>):</span>
    <span class="hljs-string">'''
    Function to remove mentions, preceded by @, in a Pandas Series

    Parameters:
        input_text : text to clean
    Output:
        cleaned Pandas Series 
    '''</span>
    <span class="hljs-keyword">return</span> re.sub(<span class="hljs-string">r'@\w+'</span>, <span class="hljs-string">''</span>, input_text)
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">compare_models_by_metric</span>(<span class="hljs-params">model_1, model_2, model_hist_1, model_hist_2, metric</span>):</span>
    <span class="hljs-string">'''
    Function to compare a metric between two models 

    Parameters:
        model_hist_1 : training history of model 1
        model_hist_2 : training history of model 2
        metrix : metric to compare, loss, acc, val_loss or val_acc

    Output:
        plot of metrics of both models
    '''</span>
    metric_model_1 = model_hist_1.history[metric]
    metric_model_2 = model_hist_2.history[metric]
    e = range(<span class="hljs-number">1</span>, NB_START_EPOCHS + <span class="hljs-number">1</span>)

    metrics_dict = {
        <span class="hljs-string">'acc'</span> : <span class="hljs-string">'Training Accuracy'</span>,
        <span class="hljs-string">'loss'</span> : <span class="hljs-string">'Training Loss'</span>,
        <span class="hljs-string">'val_acc'</span> : <span class="hljs-string">'Validation accuracy'</span>,
        <span class="hljs-string">'val_loss'</span> : <span class="hljs-string">'Validation loss'</span>
    }

    metric_label = metrics_dict[metric]
    plt.plot(e, metric_model_1, <span class="hljs-string">'bo'</span>, label=model_1.name)
    plt.plot(e, metric_model_2, <span class="hljs-string">'b'</span>, label=model_2.name)
    plt.xlabel(<span class="hljs-string">'Epoch number'</span>)
    plt.ylabel(metric_label)
    plt.title(<span class="hljs-string">'Comparing '</span> + metric_label + <span class="hljs-string">' between models'</span>)
    plt.legend()
    plt.show()

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">optimal_epoch</span>(<span class="hljs-params">model_hist</span>):</span>
    <span class="hljs-string">'''
    Function to return the epoch number where the validation loss is
    at its minimum

    Parameters:
        model_hist : training history of model
    Output:
        epoch number with minimum validation loss
    '''</span>
    min_epoch = np.argmin(model_hist.history[<span class="hljs-string">'val_loss'</span>]) + <span class="hljs-number">1</span>
    print(<span class="hljs-string">"Minimum validation loss reached in epoch {}"</span>.format(min_epoch))
    <span class="hljs-keyword">return</span> min_epoch
</code></pre>
<h1 id="heading-data-preparation">Data preparation</h1>
<h2 id="heading-data-cleaning">Data cleaning</h2>
<p>We load the CSV with the tweets and perform a random shuffle. It’s a good practice to shuffle the data before splitting between a train and test set. That way the sentiment classes are equally distributed over the train and test sets. We’ll only keep the <strong>text</strong> column as input and the <strong>airline_sentiment</strong> column as the target.</p>
<p>The next thing we’ll do is <strong>remove </strong>stopwords<strong>**. Stopwords do not have any value for predicting the sentiment. Furthermore, as we want to build a model that can be used for other airline companies as well, we </strong>remove the mentions**.</p>
<pre><code class="lang-python">df = pd.read_csv(input_path / <span class="hljs-string">'Tweets.csv'</span>)
df = df.reindex(np.random.permutation(df.index))  
df = df[[<span class="hljs-string">'text'</span>, <span class="hljs-string">'airline_sentiment'</span>]]
df.text = df.text.apply(remove_stopwords).apply(remove_mentions)
</code></pre>
<h2 id="heading-train-test-split">Train-Test split</h2>
<p>The evaluation of the model performance needs to be done on a separate test set. As such, we can estimate how well the model generalizes. This is done with the <strong>train_test_split</strong> method of scikit-learn.</p>
<pre><code>X_train, X_test, y_train, y_test = train_test_split(df.text, df.airline_sentiment, test_size=<span class="hljs-number">0.1</span>, random_state=<span class="hljs-number">37</span>)
</code></pre><h2 id="heading-converting-words-to-numbers">Converting words to numbers</h2>
<p>To use the text as input for a model, we first need to convert the words into tokens, which simply means converting the words into integers that refer to an index in a dictionary. Here we will only keep the most frequent words in the training set.</p>
<p>We clean up the text by applying <strong>filters</strong> and putting the words to <strong>lowercase</strong>. Words are separated by spaces.</p>
<pre><code class="lang-python">tk = Tokenizer(num_words=NB_WORDS,
               filters=<span class="hljs-string">'!"#$%&amp;()*+,-./:;&lt;=&gt;?@[\\]^_`{"}~\t\n'</span>,
               lower=<span class="hljs-literal">True</span>,
               char_level=<span class="hljs-literal">False</span>,
               split=<span class="hljs-string">' '</span>)
tk.fit_on_texts(X_train)
</code></pre>
<p>After having created the dictionary we can convert the text of a tweet to a vector with NB_WORDS values. With <strong>mode=binary</strong>, it contains an indicator whether the word appeared in the tweet or not. This is done with the <strong>texts_to_matrix</strong> method of the Tokenizer.</p>
<pre><code class="lang-python">X_train_oh = tk.texts_to_matrix(X_train, mode=<span class="hljs-string">'binary'</span>)
X_test_oh = tk.texts_to_matrix(X_test, mode=<span class="hljs-string">'binary'</span>)
</code></pre>
<h2 id="heading-converting-the-target-classes-to-numbers">Converting the target classes to numbers</h2>
<p>We need to convert the target classes to numbers as well, which in turn are one-hot-encoded with the <strong>to_categorical</strong> method in Keras.</p>
<pre><code class="lang-python">le = LabelEncoder()
y_train_le = le.fit_transform(y_train)
y_test_le = le.transform(y_test)
y_train_oh = to_categorical(y_train_le)
y_test_oh = to_categorical(y_test_le)
</code></pre>
<h2 id="heading-splitting-off-a-validation-set">Splitting off a validation set</h2>
<p>Now that our data is ready, we split off a validation set. This validation set will be used to evaluate the model performance when we tune the parameters of the model.</p>
<pre><code class="lang-python">X_train_rest, X_valid, y_train_rest, y_valid = train_test_split(X_train_oh, y_train_oh, test_size=<span class="hljs-number">0.1</span>, random_state=<span class="hljs-number">37</span>)
</code></pre>
<h1 id="heading-deep-learning">Deep learning</h1>
<h2 id="heading-creating-a-model-that-overfits">Creating a model that overfits</h2>
<p>We start with a model that overfits. It has 2 densely connected layers of 64 elements. The <strong>input_shape</strong> for the first layer is equal to the number of words we kept in the dictionary and for which we created one-hot-encoded features.</p>
<p>As we need to predict 3 different sentiment classes, the last layer has 3 elements. The <strong>softmax</strong> activation function makes sure the three probabilities sum up to 1.</p>
<p>The number of parameters to train is computed as <strong>(nb inputs x nb elements in hidden layer) + nb bias terms</strong>. The number of inputs for the first layer equals the number of words in our corpus. The subsequent layers have the number of outputs of the previous layer as inputs. So the number of parameters per layer are:</p>
<ul>
<li>First layer : (10000 x 64) + 64 = 640064</li>
<li>Second layer : (64 x 64) + 64 = 4160</li>
<li>Last layer : (64 x 3) + 3 = 195</li>
</ul>
<pre><code class="lang-python">base_model = models.Sequential()
base_model.add(layers.Dense(<span class="hljs-number">64</span>, activation=<span class="hljs-string">'relu'</span>, input_shape=(NB_WORDS,)))
base_model.add(layers.Dense(<span class="hljs-number">64</span>, activation=<span class="hljs-string">'relu'</span>))
base_model.add(layers.Dense(<span class="hljs-number">3</span>, activation=<span class="hljs-string">'softmax'</span>))
base_model.name = <span class="hljs-string">'Baseline model'</span>
</code></pre>
<p>Because this project is a multi-class, single-label prediction, we use <strong>categorical_crossentropy</strong> as the loss function and <strong>softmax</strong> as the final activation function. We fit the model on the train data and validate on the validation set. We run for a predetermined number of epochs and will see when the model starts to overfit.</p>
<pre><code class="lang-python">base_history = deep_model(base_model, X_train_rest, y_train_rest, X_valid, y_valid)
base_min = optimal_epoch(base_history)
eval_metric(base_model, base_history, <span class="hljs-string">'loss'</span>)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/0_ZwKhGQkYF3FqQlhe.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>In the beginning, the <strong>validation loss</strong> goes down. But at epoch 3 this stops and the validation loss starts increasing rapidly. This is when the models begin to overfit.</p>
<p>The <strong>training loss</strong> continues to go down and almost reaches zero at epoch 20. This is normal as the model is trained to fit the train data as well as possible.</p>
<h1 id="heading-handling-overfitting">Handling overfitting</h1>
<p>Now, we can try to do something about the overfitting. There are different options to do that.</p>
<ul>
<li><strong>Reduce the network’s capacity</strong> by removing layers or reducing the number of elements in the hidden layers</li>
<li>Apply <strong>regularization</strong>, which comes down to adding a cost to the loss function for large weights</li>
<li>Use <strong>Dropout layers</strong>, which will randomly remove certain features by setting them to zero</li>
</ul>
<h2 id="heading-reducing-the-networks-capacity">Reducing the network’s capacity</h2>
<p>Our first model has a large number of trainable parameters. The higher this number, the easier the model can memorize the target class for each training sample. Obviously, this is not ideal for generalizing on new data.</p>
<p>By lowering the capacity of the network, you force it to learn the patterns that matter or that minimize the loss. On the other hand, reducing the network’s capacity too much will lead to <strong>underfitting</strong>. The model will not be able to learn the relevant patterns in the train data.</p>
<p>We reduce the network’s capacity by removing one hidden layer and lowering the number of elements in the remaining layer to 16.</p>
<pre><code class="lang-python">reduced_model = models.Sequential()
reduced_model.add(layers.Dense(<span class="hljs-number">16</span>, activation=<span class="hljs-string">'relu'</span>, input_shape=(NB_WORDS,)))
reduced_model.add(layers.Dense(<span class="hljs-number">3</span>, activation=<span class="hljs-string">'softmax'</span>))
reduced_model.name = <span class="hljs-string">'Reduced model'</span>
reduced_history = deep_model(reduced_model, X_train_rest, y_train_rest, X_valid, y_valid)
reduced_min = optimal_epoch(reduced_history)
eval_metric(reduced_model, reduced_history, <span class="hljs-string">'loss'</span>)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/0_ZDi9EJn6dORo4LCY.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>We can see that it takes more epochs before the reduced model starts overfitting. The validation loss also goes up slower than our first model.</p>
<pre><code class="lang-python">compare_models_by_metric(base_model, reduced_model, base_history, reduced_history, <span class="hljs-string">'val_loss'</span>)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/0_W8RSZtaBR-SDIGn5.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>When we compare the validation loss of the baseline model, it is clear that the reduced model starts overfitting at a later epoch. The validation loss stays lower much longer than the baseline model.</p>
<h2 id="heading-applying-regularization">Applying regularization</h2>
<p>To address overfitting, we can apply weight regularization to the model. This will add a cost to the loss function of the network for large weights (or parameter values). As a result, you get a simpler model that will be forced to learn only the relevant patterns in the train data.</p>
<p>There are <strong>L1 regularization and L2 regularization</strong>.</p>
<ul>
<li>L1 regularization will add a cost with regards to the <strong>absolute value of the parameters</strong>. It will result in some of the weights to be equal to zero.</li>
<li>L2 regularization will add a cost with regards to the <strong>squared value of the parameters</strong>. This results in smaller weights.</li>
</ul>
<p>Let’s try with L2 regularization.</p>
<pre><code class="lang-python">reg_model = models.Sequential()
reg_model.add(layers.Dense(<span class="hljs-number">64</span>, kernel_regularizer=regularizers.l2(<span class="hljs-number">0.001</span>), activation=<span class="hljs-string">'relu'</span>, input_shape=(NB_WORDS,)))
reg_model.add(layers.Dense(<span class="hljs-number">64</span>, kernel_regularizer=regularizers.l2(<span class="hljs-number">0.001</span>), activation=<span class="hljs-string">'relu'</span>))
reg_model.add(layers.Dense(<span class="hljs-number">3</span>, activation=<span class="hljs-string">'softmax'</span>))
reg_model.name = <span class="hljs-string">'L2 Regularization model'</span>
reg_history = deep_model(reg_model, X_train_rest, y_train_rest, X_valid, y_valid)
reg_min = optimal_epoch(reg_history)
</code></pre>
<p>For the regularized model we notice that it starts overfitting in the same epoch as the baseline model. However, the loss increases much slower afterward.</p>
<pre><code class="lang-python">eval_metric(reg_model, reg_history, <span class="hljs-string">'loss'</span>)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/0_4UV4tgegrn6UOdRX.png" alt="Image" width="600" height="400" loading="lazy"></p>
<pre><code class="lang-python">compare_models_by_metric(base_model, reg_model, base_history, reg_history, <span class="hljs-string">'val_loss'</span>)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/0_5ybMcTqkOXyC7xc4.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h2 id="heading-adding-dropout-layers">Adding dropout layers</h2>
<p>The last option we’ll try is to add dropout layers. A dropout layer will randomly set output features of a layer to zero.</p>
<pre><code class="lang-python">drop_model = models.Sequential()
drop_model.add(layers.Dense(<span class="hljs-number">64</span>, activation=<span class="hljs-string">'relu'</span>, input_shape=(NB_WORDS,)))
drop_model.add(layers.Dropout(<span class="hljs-number">0.5</span>))
drop_model.add(layers.Dense(<span class="hljs-number">64</span>, activation=<span class="hljs-string">'relu'</span>))
drop_model.add(layers.Dropout(<span class="hljs-number">0.5</span>))
drop_model.add(layers.Dense(<span class="hljs-number">3</span>, activation=<span class="hljs-string">'softmax'</span>))
drop_model.name = <span class="hljs-string">'Dropout layers model'</span>
drop_history = deep_model(drop_model, X_train_rest, y_train_rest, X_valid, y_valid)
drop_min = optimal_epoch(drop_history)
eval_metric(drop_model, drop_history, <span class="hljs-string">'loss'</span>)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/0_B0SuqLpCTYGP4Bwz.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The model with dropout layers starts overfitting later than the baseline model. The loss also increases slower than the baseline model.</p>
<pre><code class="lang-python">compare_models_by_metric(base_model, drop_model, base_history, drop_history, <span class="hljs-string">'val_loss'</span>)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/0_ykk8IT9v3wgsq1Wf.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>The model with the dropout layers starts overfitting later. Compared to the baseline model the loss also remains much lower.</p>
<h1 id="heading-training-on-the-full-train-data-and-evaluation-on-test-data">Training on the full train data and evaluation on test data</h1>
<p>At first sight, the reduced model seems to be the best model for generalization. But let’s check that on the test set.</p>
<pre><code class="lang-python">base_results = test_model(base_model, X_train_oh, y_train_oh, X_test_oh, y_test_oh, base_min)
reduced_results = test_model(reduced_model, X_train_oh, y_train_oh, X_test_oh, y_test_oh, reduced_min)
reg_results = test_model(reg_model, X_train_oh, y_train_oh, X_test_oh, y_test_oh, reg_min)
drop_results = test_model(drop_model, X_train_oh, y_train_oh, X_test_oh, y_test_oh, drop_min)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/01/1_faz4dZBCsh3yB6tAZzSXkg.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>As shown above, all three options help to reduce overfitting. We manage to increase the accuracy on the test data substantially. Among these three options, the model with the dropout layers performs the best on the test data.</p>
<p>You can find the notebook on <a target="_blank" href="https://github.com/bertcarremans/TwitterUSAirlineSentiment/blob/master/source/Handling%20overfitting%20in%20deep%20learning%20models.ipynb">GitHub</a>. Have fun with it!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
