<?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" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Caleb Epelle on Medium]]></title>
        <description><![CDATA[Stories by Caleb Epelle on Medium]]></description>
        <link>https://medium.com/@calebepelle5?source=rss-46c7ffd9b1b2------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*FcLB8tee8YZ7lTEc11cghA.jpeg</url>
            <title>Stories by Caleb Epelle on Medium</title>
            <link>https://medium.com/@calebepelle5?source=rss-46c7ffd9b1b2------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sat, 16 May 2026 14:53:07 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@calebepelle5/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Predictive Maintenance on Cement Kiln Machinery]]></title>
            <link>https://medium.com/@calebepelle5/predictive-maintenance-on-kiln-refractory-lining-ead7af86fade?source=rss-46c7ffd9b1b2------2</link>
            <guid isPermaLink="false">https://medium.com/p/ead7af86fade</guid>
            <dc:creator><![CDATA[Caleb Epelle]]></dc:creator>
            <pubDate>Mon, 26 Jan 2026 12:55:22 GMT</pubDate>
            <atom:updated>2026-02-02T19:44:13.780Z</atom:updated>
            <content:encoded><![CDATA[<p>In 2026, I started a job at a Cement Manufacturing Company, and I saw how simple failures of critical equipment could cause financial losses and product losses.</p><p>So I decided to build a system that could predict failures before they actually occur in order to save cost and valuable products.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/460/1*9kaW-vsFDylhyl-undrjZw.jpeg" /></figure><p>I tested multiple models on this project, but settled on 2.</p><p>By using these models, I believe manufacturers can be better positioned to maintain their equipment before they develop critical problems, as they would have a sort of “foresight”.</p><p>I was able to achieve the following results and identify and rank the most influential variables (features) involved in machinery failure.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/633/1*tHajhyefCg3fSXx0rxdLOw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/636/1*vy-0fs3jrN6ODbAV3Va2Hw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/634/1*8lFJebc2B_lmfhzjdj_KCQ.png" /><figcaption>Performance Metrics of Random Forest Model</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/635/1*xC082rXtxAbwboI8g6vSlQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/632/1*rYM8XDmlLduOPfXiQSXLGg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/632/1*5Vx9HQ7FSQnlmWosCvySdg.png" /><figcaption>Performance Metrics of XGBoost Model</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/602/1*AhyKfkvyjNgpMeMgK3BbAQ.png" /><figcaption>Performance Metrics of Random Forest &amp; XGBoost Models</figcaption></figure><p>With this, Plant Managers, Inspectors, and Maintenance Personnel would have insight into the <strong>“health status” </strong>of their equipment and machines.</p><p>****************************************************************************</p><p>Now for the technical bit.</p><p>I downloaded the data from Kaggle</p><p>It contained 10,000 observations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1008/1*HZKG25mPPJ7KWxnvyF4lUQ.png" /><figcaption>Dataset</figcaption></figure><p>I imported all necessary libraries and loaded the dataset.</p><pre>import pandas as pd<br>import numpy as np<br>import matplotlib.pyplot as plt<br>import seaborn as sns<br>from imblearn.over_sampling import SMOTE<br>from sklearn.ensemble import RandomForestClassifier<br>import xgboost as xgb<br>from tensorflow.keras.models import Sequential<br>from tensorflow.keras.layers import Dense, LSTM, Dropout<br>from tensorflow.keras.optimizers import Adam<br>from sklearn.model_selection import train_test_split<br>from sklearn.preprocessing import StandardScaler<br>from sklearn.metrics import classification_report, confusion_matrix, roc_auc_score, roc_curve<br><br><br>df = pd.read_csv(&quot;C:/Users/USER/Desktop/port/predictive_maintenance.csv&quot;)<br>print(&quot;DATA LOADED&quot;)<br>print(df.head())<br>print(df)</pre><p>I cleaned the data, converted numbers that were strings into numbers, dropped irrelevant features and encoded features for easy processing.</p><pre>df = df.iloc[:, 0].str.split(&quot;\t&quot;, expand=True)<br><br>df.columns = [<br>    &quot;UDI&quot;,<br>    &quot;Product ID&quot;,<br>    &quot;Type&quot;,<br>    &quot;Air temperature K&quot;,<br>    &quot;Process temperature K&quot;,<br>    &quot;Rotational speed rpm&quot;,<br>    &quot;Torque Nm&quot;,<br>    &quot;Tool wear min&quot;,<br>    &quot;Target&quot;,<br>    &quot;Failure Type&quot;<br>]<br><br>df[&quot;Failure Type&quot;] = df[&quot;Failure Type&quot;].str.replace(&quot;...&quot;, &quot;&quot;, regex=False)<br>print(&quot;CLEANED DF&quot;)<br>print(df.head())<br><br>df = df.drop(columns=[&quot;Failure Type&quot;, &quot;UDI&quot;, &quot;Product ID&quot;])<br>print(&quot;DROPPED COLUMNS DF&quot;)<br>print(df.head())<br>print(df.describe())<br>print(df.value_counts())<br><br>df[&quot;Type&quot;], uniques = pd.factorize(df[&quot;Type&quot;])<br>print(&quot;ENCODED COLUMNS DF&quot;)<br>print(df.head())</pre><p>Then I split the data into training and testing sets and scaled them for easy training, made sure that both the features and labels were of the numeric type, and oversampled the data for uniformity in training data.</p><pre>x = df.drop(columns=[&quot;Target&quot;])<br>print(&quot;FEATURES&quot;)<br>print(x)<br><br>y = df[&quot;Target&quot;]<br>print(&quot;TARGET&quot;)<br>print(y)<br></pre><pre># Ensure x is numeric<br>for col in x.columns:<br>    x[col] = pd.to_numeric(x[col], errors=&#39;coerce&#39;)  # converts invalid values to NaN<br><br># Ensure y is numeric<br>y = y.astype(int)</pre><pre># Splitting data<br>x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.2, random_state=42, stratify=y)<br><br># Scaling for neural networks and LSTM<br>scaler = StandardScaler()<br>x_train_scaled = scaler.fit_transform(x_train)<br>x_test_scaled = scaler.transform(x_test)</pre><pre># Oversampling for uniformity<br>smote = SMOTE(random_state=42)<br><br>print(&quot;Original y_train distribution:&quot;)<br>print(y_train.value_counts())<br><br># Apply SMOTE to training data only<br>x_train, y_train = smote.fit_resample(x_train, y_train)<br><br># Check the new distribution<br>print(&quot;Resampled y_train distribution:&quot;)<br>print(pd.Series(y_train).value_counts())</pre><p>I used 4 models:</p><ol><li>Random Forest Classifier</li><li>XG Boost</li><li>Deep Learning Neural Network</li><li>LSTM</li></ol><p>After fitting and training these models, I evaluated them to see how well they performed against each other.</p><pre>print(f&quot;*******************RANDOM FOREST Classification Report*******************&quot;)<br>print(classification_report(y_test, y_pred_rf))  <br><br>print(f&quot;*******************XGBOOST Classification Report*******************&quot;)<br>print(classification_report(y_test, y_pred_xgb)) <br><br>print(f&quot;*******************DEEP NEURAL NETWORK Classification Report*******************&quot;)<br>print(classification_report(y_test, y_pred_nn))<br><br>print(f&quot;*******************LSTM Classification Report*******************&quot;)<br>print(classification_report(y_test, y_pred_lstm))</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/602/1*AhyKfkvyjNgpMeMgK3BbAQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/680/1*CKWWc_YwRM_jdK7-haR7UA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/520/1*gp_-d9mmEbjyW262Q22roA.png" /><figcaption>Model Performance of Random Forest, XGBoost, Deep Learning Neural Network and LSTM Models</figcaption></figure><p>Seeing that my desired model would predict when a failure is about to occur, the event where it would predict a “<strong>no failure” </strong>when there is in fact a “<strong>failure (false negative) </strong>would be a more serious problem compared to the event where it would predict a “<strong>failure” </strong>and there is in fact “<strong>no failure” (false positive)</strong>.</p><p>So I decided to focus my model appraisal on the “<strong>RECALL” </strong>metric, which is best suited for <strong>“FALSE NEGATIVES” </strong>as opposed to<strong> “PRECISION”, </strong>which is best suited for “<strong>FALSE POSITIVES”.</strong></p><p>From this, I chose the models with the best recall:</p><ol><li>Random Forest</li><li>XGBoost</li></ol><figure><img alt="" src="https://cdn-images-1.medium.com/max/633/1*tHajhyefCg3fSXx0rxdLOw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/636/1*vy-0fs3jrN6ODbAV3Va2Hw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/634/1*8lFJebc2B_lmfhzjdj_KCQ.png" /><figcaption>Confusion Matrix, AUC-ROC &amp; Feature Importance Plots of Random Forest Model</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/635/1*xC082rXtxAbwboI8g6vSlQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/632/1*rYM8XDmlLduOPfXiQSXLGg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/632/1*5Vx9HQ7FSQnlmWosCvySdg.png" /><figcaption>Confusion Matrix, AUC-ROC &amp; Feature Importance Plots of XGBoost Model</figcaption></figure><p>From these models, I intend to further refine and increase their baseline recalls by finetuning their hyperparameters.</p><p>****************************************************************************</p><p>Now that I had narrowed down my models and analyzed the data to find out what factors contribute the most to equipment failure, I carried out predictions on random data to determine if there would be equipment failure.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/547/1*RuFqD_xOph96YzBaEhqyRg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/598/1*vuiORMO28S1SGrjnF3qpUw.png" /><figcaption>Predictions from Random Forest and XGBoost Models</figcaption></figure><p>From the pictures above, it is clear that there are a few false negatives and that the average probability of failure on these false negatives is 30% but the lowest is around 10%</p><p>One solution to solving the false negatives problem could be lowering the positive detection probability from 50% to 10%.</p><p>This would make the model predictions <strong>VERY STRICT </strong>and would <strong>decrease </strong>the<strong> chances of the model predicting “no failure” when there is in fact a “failure”.</strong></p><pre>threshold = 0.1   # lower than 0.5 = fewer missed failures<br><br># Convert probabilities to predictions<br>y_pred_rf_thresh = (y_prob_rf &gt;= threshold).astype(int)<br><br>print(&quot;Failure probabilities:&quot;)<br>print(y_prob_rf)<br><br>print(f&quot;Prediction of failure using threshold = {threshold}:&quot;)<br>print(y_pred_rf_thresh)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/686/1*tyUV5KDRzxQ5ciE-rAOfvw.png" /></figure><p>By <strong>“tightening” </strong>the prediction parameters on the Random Forest model, I was able to <strong>eliminate</strong> the model’s <strong>false-negative </strong>problem by increasing the <strong>recall from 73.5% to 95.9% </strong>while maintaining an <strong>accuracy of 86.8%, </strong>which would lead to a <strong>system better equipped to predict equipment failure beforehand.</strong></p><p>In the future, I hope to do the following:</p><p><strong>FUTURE VERSION UPGRADES</strong></p><ol><li>Model hyperparameters to be finetuned</li><li>The model will monitor real-time events to know when failure is imminent (possibly by using Autoencoders, which are good for systems without data from use [new equipment])</li><li>The model should detect anomalies using autoencoders</li><li>The model should be able to discern the type of failure</li></ol><p><strong><em>THANK YOU FOR READING THIS FAR!!</em></strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ead7af86fade" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AI Job Application Automation]]></title>
            <link>https://medium.com/@calebepelle5/ai-job-application-automation-a84e6caf66d7?source=rss-46c7ffd9b1b2------2</link>
            <guid isPermaLink="false">https://medium.com/p/a84e6caf66d7</guid>
            <dc:creator><![CDATA[Caleb Epelle]]></dc:creator>
            <pubDate>Fri, 02 Jan 2026 17:08:53 GMT</pubDate>
            <atom:updated>2026-01-03T04:24:10.430Z</atom:updated>
            <content:encoded><![CDATA[<h3>AI Agent Job Application Automation</h3><p>In 2024, I left my job in the oil and gas industry to pursue a life and a job in the tech industry.</p><p>I quickly realized that getting these jobs was not so easy and the application process was monotonous, tedious, boring and tiring.</p><p>So I created an AI Agent to handle all my job applications and schedule interviews.</p><p>This was the result.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*0vaM2XS32D09FZsYGmfdCA.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*OoWeMjpP9bLzL999hzVV3Q.jpeg" /></figure><p>Automating my job application process</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a84e6caf66d7" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Customer Churn Prediction]]></title>
            <link>https://medium.com/@calebepelle5/customer-churn-1646b873df37?source=rss-46c7ffd9b1b2------2</link>
            <guid isPermaLink="false">https://medium.com/p/1646b873df37</guid>
            <dc:creator><![CDATA[Caleb Epelle]]></dc:creator>
            <pubDate>Fri, 31 Oct 2025 04:37:12 GMT</pubDate>
            <atom:updated>2026-01-06T05:59:43.875Z</atom:updated>
            <content:encoded><![CDATA[<p>I started a business a little while after I left school and I saw and felt how disheartening it is when customers and clients leave or when they don’t patronize you as much as they used to <em>(or as much you’d like them to). </em>So, I used AI to predict what kind of customers are likely to leave you (Churn), your service or your product as well as identify factors, qualities and traits that heavily influence client retention.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*b26FsGUkgC2acMW5NJ7oCg.jpeg" /></figure><p>I used a couple models to predict this. By comparing the predictions of these models, I believe business owners can improve their customer retention as well as customer satisfaction.</p><p>The data used here was from a telecom company. It comprised of variables like; products and services the customer paid for, their total bills as well as whether they had churned or not.</p><p>By carrying out my analysis and prediction, I was able to identify the key factors that contributed to customer retention.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*AaoO2NyGMPLQqDkSG_XoHw.png" /><figcaption>Bar plot showing the 10 most important factors that contribute to customer retention across all models</figcaption></figure><p>With this, business owners would have insight into their customer’s minds to know what they consider “<strong>important</strong>”.</p><p><strong>What services to offer and cut to improve customer retention</strong></p><p>Now for the technical bit.</p><p>I imported all necessary libraries and loaded the dataset.</p><pre>import pandas as pd<br>import numpy as np<br>import seaborn as sns<br>import matplotlib.pyplot as plt<br>from sklearn.model_selection import train_test_split<br>from sklearn.preprocessing import StandardScaler<br>from sklearn.metrics import (<br>    accuracy_score,<br>    classification_report,<br>    confusion_matrix,<br>    roc_curve,<br>    auc<br>)<br>from sklearn.ensemble import RandomForestClassifier<br>from sklearn.linear_model import LogisticRegression<br>from xgboost import XGBClassifier<br><br>df = pd.read_csv(&quot;C:/Users/USER/Desktop/port/WA_Fn-UseC_-Telco-Customer-Churn.csv&quot;)<br>print(&quot;Data loaded successfully!&quot;)<br>print(df.head())</pre><p>Cleaned the data, converted numbers that were strings into numbers, removed irrelevant features, filled in missing values and encoded features for easy processing.</p><pre>df[&quot;TotalCharges&quot;] = df[&quot;TotalCharges&quot;].replace(&quot; &quot;, np.nan)<br>df[&quot;TotalCharges&quot;] = pd.to_numeric(df[&quot;TotalCharges&quot;], errors=&quot;coerce&quot;)<br><br>df[&quot;TotalCharges&quot;] = df[&quot;TotalCharges&quot;].fillna(df[&quot;TotalCharges&quot;].median())<br><br>if &quot;customerID&quot; in df.columns:<br>    df = df.drop(&quot;customerID&quot;, axis=1)<br><br>cat_cols = df.select_dtypes(include=[&quot;object&quot;]).columns.tolist()<br><br>for col in cat_cols:<br>    if df[col].nunique() == 2:<br>        df[col] = df[col].map({&quot;Yes&quot;: 1, &quot;No&quot;: 0})<br>    else:<br>        df = pd.get_dummies(df, columns=[col], drop_first=True)</pre><p>Then I split the data into training and testing sets and scaled the for easy training.</p><pre>X = df.drop(&quot;Churn&quot;, axis=1)<br>y = df[&quot;Churn&quot;]<br><br>X = X.fillna(X.median())<br><br>X_train, X_test, y_train, y_test = train_test_split(<br>    X, y, test_size=0.2, random_state=42, stratify=y<br>)<br><br>scaler = StandardScaler()<br>X_train = X_train.fillna(X_train.median())<br>X_test = X_test.fillna(X_test.median())<br><br>X_train_scaled = scaler.fit_transform(X_train)<br>X_test_scaled = scaler.transform(X_test)</pre><p>I used 3 models:</p><ol><li>Random Forest Classifier</li><li>Logistic Regression</li><li>XG Boost</li></ol><p>After fitting and training these models, I evaluated them to see how well they performed against each other.</p><pre>def evaluate_model(name, y_true, y_pred):<br>    print(f&quot;******************** {name} Performance ********************&quot;)<br>    print(&quot;Accuracy:&quot;, round(accuracy_score(y_true, y_pred), 4))<br>    print(classification_report(y_true, y_pred))<br><br>evaluate_model(&quot;Random Forest&quot;, y_test, rf_pred)<br>evaluate_model(&quot;Logistic Regression&quot;, y_test, lr_pred)<br>evaluate_model(&quot;XGBoost&quot;, y_test, xgb_pred)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/628/1*0vDNcVuisWL3NVEMxGIKBQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/634/1*8F3DKNXcWkjhegWtqtyIlA.png" /><figcaption>Results from model evaluation</figcaption></figure><p>I also made confusion matrices and ROC-AUC curves to see which model had better success dealing with positives and negatives, both true and false, and to analyze model performance.</p><pre># RANDOM FOREST CONFUSION MATRIX<br>cm = confusion_matrix(y_test, rf_pred)<br>sns.heatmap(cm, annot=True, fmt=&quot;d&quot;, cmap=&quot;Blues&quot;)<br>plt.title(&quot;Confusion Matrix - Random Forest&quot;)<br>plt.xlabel(&quot;Predicted&quot;)<br>plt.ylabel(&quot;Actual&quot;)<br>plt.show()<br><br># XGBOOST CONFUSION MATRIX<br>cm = confusion_matrix(y_test, xgb_pred)<br>sns.heatmap(cm, annot=True, fmt=&quot;d&quot;, cmap=&quot;Blues&quot;)<br>plt.title(&quot;Confusion Matrix - XG Boost&quot;)<br>plt.xlabel(&quot;Predicted&quot;)<br>plt.ylabel(&quot;Actual&quot;)<br>plt.show()<br><br># LINEAR REGRESSION CONFUSION MATRIX<br>cm = confusion_matrix(y_test, lr_pred)<br>sns.heatmap(cm, annot=True, fmt=&quot;d&quot;, cmap=&quot;Blues&quot;)<br>plt.title(&quot;Confusion Matrix - Linear Regression&quot;)<br>plt.xlabel(&quot;Predicted&quot;)<br>plt.ylabel(&quot;Actual&quot;)<br>plt.show()<br><br># ROC-AUC<br>rf_fpr, rf_tpr, _ = roc_curve(y_test, rf_prob)<br>lr_fpr, lr_tpr, _ = roc_curve(y_test, lr_prob)<br>xgb_fpr, xgb_tpr, _ = roc_curve(y_test, xgb_prob)<br><br>plt.figure(figsize=(8,6))<br>plt.plot(rf_fpr, rf_tpr, label=f&quot;Random Forest (AUC = {auc(rf_fpr, rf_tpr):.3f})&quot;)<br>plt.plot(lr_fpr, lr_tpr, label=f&quot;Logistic Regression (AUC = {auc(lr_fpr, lr_tpr):.3f})&quot;)<br>plt.plot(xgb_fpr, xgb_tpr, label=f&quot;XGBoost (AUC = {auc(xgb_fpr, xgb_tpr):.3f})&quot;)<br>plt.plot([0,1], [0,1], &#39;k--&#39;, label=&quot;Random Guess&quot;)<br>plt.xlabel(&quot;False Positive Rate&quot;)<br>plt.ylabel(&quot;True Positive Rate&quot;)<br>plt.title(&quot;ROC Curves Comparison&quot;)<br>plt.legend()<br>plt.show()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*aq-hUhDAp2GGNzX6NrqXjg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*3gRbZYtQsMDDDkI1C37oAQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*qX2a3WgJUnPAQyXyuDXSbg.png" /><figcaption>Confusion matrix for each model, showing how well they make predictions</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/1*d8C95NVncMKUXdYJuxwYGg.png" /><figcaption>ROC-AUC curve for all models</figcaption></figure><p>From these evaluations I saw that the models were good and that The Logistic Regression model seemed to be making the best predictions.</p><p>I carried out feature importance tests on each model to get the features that contributed the most to the prediction of the model as I saw that this could help provide valuable insight into what makes a customer leave.</p><pre># XGBoost Feature Importance<br>xgb_importance = pd.Series(xgb.feature_importances_, index=X.columns).sort_values(ascending=False)<br>top_features_xgb = xgb_importance.head(15)<br><br>plt.figure(figsize=(10,6))<br>sns.barplot(x=top_features_xgb.values, y=top_features_xgb.index, palette=&quot;viridis&quot;)<br>plt.title(&quot;Top 15 Feature Importances (XGBoost)&quot;)<br>plt.xlabel(&quot;Importance Score&quot;)<br>plt.ylabel(&quot;Feature&quot;)<br>plt.tight_layout()<br>plt.show()<br><br># Random Forest Feature Importance<br>rf_importance = pd.Series(rf.feature_importances_, index=X.columns).sort_values(ascending=False)<br>top_features_rf = rf_importance.head(15)<br><br>plt.figure(figsize=(10,6))<br>sns.barplot(x=top_features_rf.values, y=top_features_rf.index, palette=&quot;coolwarm&quot;)<br>plt.title(&quot;Top 15 Feature Importances (Random Forest)&quot;)<br>plt.xlabel(&quot;Importance Score&quot;)<br>plt.ylabel(&quot;Feature&quot;)<br>plt.tight_layout()<br>plt.show()<br><br># Logistic Regression Feature Importance<br>lr_importance = pd.Series(lr.coef_[0], index=X.columns).abs().sort_values(ascending=False)<br>top_features_lr = lr_importance.head(15)<br><br>plt.figure(figsize=(10,6))<br>sns.barplot(x=top_features_lr.values, y=top_features_lr.index, palette=&quot;magma&quot;)<br>plt.title(&quot;Top 15 Feature Importances (Logistic Regression)&quot;)<br>plt.xlabel(&quot;Coefficient Magnitude&quot;)<br>plt.ylabel(&quot;Feature&quot;)<br>plt.tight_layout()<br>plt.show()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*eYatbn8Ah4AQumC8tsdukQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*6Kr5dbmhGUJHe4TD5ZmDzw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*Aps65rMdsPR4NYur0OPSUA.png" /><figcaption>Bar plot showing 15 most influential features in each model</figcaption></figure><p>Then I condensed this list by getting the top 10 most influential features across all three models.</p><pre>no_feat = 10<br><br># Random Forest importances<br>rf_importance = pd.Series(rf.feature_importances_, index=X.columns).sort_values(ascending=False)<br><br># XGBoost importances <br>xgb_importance = pd.Series(xgb.feature_importances_, index=X.columns).sort_values(ascending=False)<br><br># Logistic Regression importances <br>lr_importance = pd.Series(abs(lr.coef_[0]), index=X.columns).sort_values(ascending=False)<br><br># Combine top 20 features from each model<br>combined_features = pd.concat([rf_importance.head(20), xgb_importance.head(20),lr_importance.head(20)])<br><br># Remove duplicates and sort by mean importance<br>combined_mean_importance = combined_features.groupby(combined_features.index).mean().sort_values(ascending=False)<br><br># Select top 10 overall<br>top_features = combined_mean_importance.head(no_feat)<br><br>print(&quot;Top Overall Important Features (Across All Models):&quot;)<br>print(top_features)<br><br>plt.figure(figsize=(10,6))<br>sns.barplot(x=top_features.values, y=top_features.index, palette=&quot;magma&quot;)<br>plt.title(f&quot;Top {no_feat} Most Important Features (Combined Models)&quot;)<br>plt.xlabel(&quot;Average Importance Score&quot;)<br>plt.ylabel(&quot;Feature&quot;)<br>plt.tight_layout()<br>plt.show()</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1000/1*AaoO2NyGMPLQqDkSG_XoHw.png" /><figcaption>Bar plot showing 10 most influential features across all models</figcaption></figure><p>Now that I had analyzed the data to find out why people left, I carried out predictions on random data to know if a person would leave and what the chances of that person leaving were.</p><pre>random_idx = np.random.randint(0, len(X_test))<br>sample = X_test.iloc[random_idx:random_idx+1]<br><br># Ensure there are no NaNs<br>sample = sample.fillna(X_train.median())<br><br># Scale for LR &amp; RF<br>sample_scaled = scaler.transform(sample)<br><br># Make predictions<br>pred_rf = rf.predict(sample_scaled)[0]<br>pred_xgb = xgb.predict(sample)[0]<br><br># Logistic Regression (handle any NaNs)<br>if np.isnan(sample_scaled).any():<br>    print(&quot;NaNs found in sample_scaled — filling with 0 for Logistic Regression.&quot;)<br>    sample_scaled = np.nan_to_num(sample_scaled, nan=0.0)<br><br>pred_lr = lr.predict(sample_scaled)[0]<br><br>prob_rf = rf.predict_proba(sample_scaled)[0][1] * 100<br>prob_xgb = xgb.predict_proba(sample)[0][1] * 100<br>prob_lr = lr.predict_proba(sample_scaled)[0][1] * 100<br><br>prob_rf = round(prob_rf, 2)<br>prob_xgb = round(prob_xgb, 2)<br>prob_lr = round(prob_lr, 2)<br><br># Show actual value from test set<br>actual_value = y_test.iloc[random_idx]<br>print(f&quot;Actual Value (1=Churn, 0=No): {actual_value}&quot;)<br><br># shows the chances of the customer leaving/churnning btwn 0 and 1<br>print(f&quot;Random Forest Prediction (1=Churn, 0=No):, {pred_rf}, Probability: {prob_rf}% chance of leaving&quot;)<br>print(f&quot;XGBoost Prediction (1=Churn, 0=No):, {pred_xgb}, Probability: {prob_xgb}% chance of leaving&quot;)<br>print(f&quot;Logistic Regression Prediction (1=Churn, 0=No):, {pred_lr}, Probability: {prob_lr}% chance of leaving&quot;)<br><br># OUPUT RESULT<br>&quot;&quot;&quot;<br><br>Actual Value (1=Churn, 0=No): 0<br><br>Random Forest Prediction (1=Churn, 0=No):, 0, Probability: 1.0% chance of leaving<br>XGBoost Prediction (1=Churn, 0=No):, 0, Probability: 0.6000000238418579% chance of leaving<br>Logistic Regression Prediction (1=Churn, 0=No):, 0, Probability: 0.56% chance of leaving<br><br>&quot;&quot;&quot;</pre><p>With this, anyone would be able to know:</p><ol><li>What services to offer and cut to improve customer retention</li><li>Why their customers left</li><li>What makes their customers stay or leave</li><li>Whether a certain customer would leave</li><li>What to do to make customers stay <br><em>(look at feature importance plot [</em><strong><em>FIRST PLOT]</em></strong><em>)</em></li></ol><p><strong><em>THANK YOU FOR READING THIS FAR!!</em></strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=1646b873df37" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AI Quality Control and Inspection]]></title>
            <link>https://medium.com/@calebepelle5/ai-quality-control-and-inspection-a1433982a132?source=rss-46c7ffd9b1b2------2</link>
            <guid isPermaLink="false">https://medium.com/p/a1433982a132</guid>
            <dc:creator><![CDATA[Caleb Epelle]]></dc:creator>
            <pubDate>Tue, 28 Oct 2025 09:53:25 GMT</pubDate>
            <atom:updated>2025-10-29T09:02:27.767Z</atom:updated>
            <content:encoded><![CDATA[<p>I worked as an Inspection Engineer in the Oil and Gas Industry.</p><p>One day, on an oil rig, I saw a team inspect a structure that was at a height difficult to reach. They used a drone to do this.</p><p>It got my team and I talking about the possibility of machines replacing us in the near future. Some said it was possible, others said it wasn’t, others said it would take time. <em>(can you guess what I said?)</em></p><p>I decided to try something out.</p><p>I wanted to see if I could use machines to help us rather than to replace us <em>(just like the team with the drone did)</em></p><p>A key aspect of my job as an inspector was to confirm if equipment met the standards they claimed to be designed after. One repetitive task we often underwent was measuring.</p><p>We measured things like webbing slings, wire rope slings, cargo carrying units (CCUs), chain hoists and many more.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CsKu0FYI1yySRJCPaMxxCg.jpeg" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/850/1*ujeoUJe8CwY-MXbrk-DP3w.png" /><figcaption>Cargo Carrying Unit and Webbing Slings</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/474/0*6qBdOuJiF0MoA5hm" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/800/0*uO2Owj-m9qfwRnDs.jpg" /><figcaption>Chain Hoist and Wire Rope Sling</figcaption></figure><p>I decided to take on that part of the job with Artificial Intelligence.</p><p>I designed a Computer Vision System that could get the dimensions of any object it saw.</p><p>This was the result.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*AHOq__T1hUnsB8Chj1c1tQ.png" /><figcaption>Result displaying the length, width and area or an object</figcaption></figure><p>I was able to accurately measure the dimensions of an object and display these values to the user.</p><p>This could help cut down on the time spent inspecting individual items which would in turn improve the efficiency of an inspector.</p><p>To do this I had to generate live video feed</p><pre>cam = True#this could be used to toggle camera on/off(true = on)<br><br># static image<br>ruler = cv2.imread(&quot;pictures/ruler 2.jpg&quot;)<br><br>cap1 = cv2.VideoCapture(0)<br>frame_width = 640<br>frame_height = 480<br>cap1.set(3,frame_width)#width<br>cap1.set(4,frame_height)#height<br>cap1.set(10,100)#brightness/exposure<br><br>while True:<br>    if cam:<br>        success, img = cap1.read()<br>    else:<br>        img = ruler<br><br>    cv2.imshow(&quot;video&quot;,img)<br>    if cv2.waitKey(1) &amp; 0xFF ==ord(&#39;s&#39;):<br>        break</pre><p>Find contours/edges of objects of objects using the canny edge detection and a variable filter for different number of shapes</p><pre>img, final_contours = functions.get_contours(<br>    img, show_canny=False, draw=True, min_area=1000, filter=4<br>)</pre><p>Flatten the Image so it can be measured</p><pre>imgwarp = functions.get_warp(img, biggest, 360, 480)</pre><p>Carry out the measurement</p><pre>ordered_points = functions.order_point(biggest)<br>obj_width = round(<br>    (functions.find_length(ordered_points[0][0] // scale,<br>                           ordered_points[1][0] // scale) / 10), 1<br>)<br>obj_length = round(<br>    (functions.find_length(ordered_points[0][0] // scale,<br>                           ordered_points[2][0] // scale) / 10), 1<br>)<br>obj_area = obj_length * obj_width</pre><p>and finally, raw lines for smooth user interface</p><pre>cv2.polylines(img, [biggest], True, (0, 255, 0), 2)<br>cv2.putText(img, f&#39;Width: {obj_width} in&#39;, (x, y - 10),<br>            cv2.FONT_HERSHEY_COMPLEX, 0.8, (0, 255, 0), 2)<br>cv2.putText(img, f&#39;Length: {obj_length} in&#39;, (x, y + h + 30),<br>            cv2.FONT_HERSHEY_COMPLEX, 0.8, (0, 255, 0), 2)<br>cv2.putText(img, f&#39;Area: {obj_area} in²&#39;, (x, y + h + 60),<br>            cv2.FONT_HERSHEY_COMPLEX, 0.8, (0, 255, 0), 2)</pre><p>I believe something like this could really help inspectors do their jobs better and faster.</p><p><strong><em>Thank you for reading this far!</em></strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a1433982a132" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Automated Data Logging]]></title>
            <link>https://medium.com/@calebepelle5/automated-data-fcb0ebd18260?source=rss-46c7ffd9b1b2------2</link>
            <guid isPermaLink="false">https://medium.com/p/fcb0ebd18260</guid>
            <dc:creator><![CDATA[Caleb Epelle]]></dc:creator>
            <pubDate>Tue, 28 Oct 2025 09:50:25 GMT</pubDate>
            <atom:updated>2025-10-28T09:54:50.035Z</atom:updated>
            <content:encoded><![CDATA[<img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fcb0ebd18260" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[AI Safety Officer]]></title>
            <link>https://medium.com/@calebepelle5/ai-safety-officer-7aa787e0d1ef?source=rss-46c7ffd9b1b2------2</link>
            <guid isPermaLink="false">https://medium.com/p/7aa787e0d1ef</guid>
            <dc:creator><![CDATA[Caleb Epelle]]></dc:creator>
            <pubDate>Tue, 28 Oct 2025 09:48:43 GMT</pubDate>
            <atom:updated>2026-01-06T06:00:25.728Z</atom:updated>
            <content:encoded><![CDATA[<p>I have worked in the Engineering Industry for about 6 years. Throughout those years, I witnessed and heard about various incidents that could have been prevented if someone had been wearing the correct PPE (Personal Protective Equipment).</p><p>I created a system that tracks individuals and identifies whether they are properly dressed in PPE before entering the field to work.</p><p>This system can be paired with my previous project on access control (<a href="https://medium.com/@calebepelle5/hands-free-access-a-new-standard-e6427630a366"><em>https://medium.com/@calebepelle5/hands-free-access-a-new-standard-e6427630a366</em></a>) to create a more robust system that denies access to anyone not properly dressed for the task at hand.</p><p><a href="https://medium.com/@calebepelle5/hands-free-access-a-new-standard-e6427630a366">Hands-Free Access: A New Standard</a></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*-XZ21qyvTtaDlHCYq8hAuQ.jpeg" /><figcaption>picture by Vitaliy Yashar</figcaption></figure><p>This was the result</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/636/1*m_KRP_-IgekHaYa73CO4Fg.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/642/1*WvDhcW8DsIaDzlSZkCJA9g.png" /><figcaption>Successful identification of an individual with and without PPE (limited to coveralls/vests), respectively</figcaption></figure><p>The first picture above shows an individual without protective equipment, while the second shows an individual with protective equipment.</p><p>To be able to do this, I had to create a custom object detection model that was trained on protective equipment commonly used in the engineering industry.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*CF60feKuvZVOcPbPODmhEA.png" /><figcaption>Training data with over 1,000 training images</figcaption></figure><pre>from ultralytics import YOLO  <br><br>data_yaml_path = &quot;C:/Users/USER/Desktop/port/yolo/PPE_DATASET/data.yaml&quot; <br>base_model = &quot;yolov8n.pt&quot; # chosen for its speed in real-time detection<br><br>epochs = 40<br>img_size = 480<br>batch_size = 16<br>device = &quot;cpu&quot;<br><br># LOAD BASE MODEL<br>model = YOLO(base_model)<br><br># MODEL TRAINING<br>model.train(<br>    data=data_yaml_path,<br>    epochs=epochs,<br>    imgsz=img_size,<br>    batch=batch_size,<br>    device=device,<br>    verbose=True,<br>)<br>trained_model_path = &quot;runs/detect/train5/weights/best.pt&quot;<br><br>print(f&quot;Training finished! Trained model saved at: {trained_model_path}&quot;)</pre><p>I immediately ran into a problem.</p><p>The model was overfitted.</p><p>It only recognized protective equipment, which led it to classify anything and everything as such.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/642/1*7wK5jwIVGpwAK66fQG4nRw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/632/1*Fahdu8tmjzjt4BpTPRTSaw.png" /><figcaption>Flawed Detections</figcaption></figure><p>To fix this, I had to train the model on everyday objects as well.</p><p>Objects like shirts, trousers, glasses, and so on.</p><p>I was able to get the following results</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Tj-hR8qehqqzieK2fz0gWw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*c2Exsc-brUz578mCLwVfEQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*57HjvQAN1nnLQpCQXv8CsA.png" /><figcaption>Performance curves showing that the model leans more towards 1.0(100%)</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*2e-WP7jj6djKLcnzTPLiZA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*nRC2IPDgbsPcZZLm_eUsJQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*u2CPt_oyJT06-c6wmJTMwg.png" /><figcaption>Confusion matrix showing suitable model performance</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Gaw6V0XJ6V_clsKTKYeUTg.png" /><figcaption>Plots of showing the model’s loss reduction as well as precision and recall increment over a training period of 40 epochs</figcaption></figure><h3><strong>Key elements of my code are below.</strong></h3><p>I set the confidence ratio to 51% to reduce false predictions</p><p>I limited my test to the “vest” class because I didn’t have a helmet lying around.</p><pre>confidence_threshold = 0.51   # Minimum confidence to show detection<br>ppe_class = &quot;Vest&quot;       # Class name for PPE coverall<br>person_class = &quot;Person&quot;      # Class name for person</pre><p>Then I used an overlap function to check when the object and person are in the same “vicinity”.</p><pre>def boxes_overlap(boxA, boxB):<br>    xA = max(boxA[0], boxB[0])<br>    yA = max(boxA[1], boxB[1])<br>    xB = min(boxA[2], boxB[2])<br>    yB = min(boxA[3], boxB[3])<br>    inter_area = max(0, xB - xA) * max(0, yB - yA)<br>    if inter_area == 0:<br>        return False<br>    boxA_area = (boxA[2] - boxA[0]) * (boxA[3] - boxA[1])<br>    boxB_area = (boxB[2] - boxB[0]) * (boxB[3] - boxB[1])<br>    iou = inter_area / float(boxA_area + boxB_area - inter_area)<br>    return iou &gt; 0.1  # Adjust for more precision and to avoid fakeouts</pre><p>I also added bounding boxes around objects for improved user interaction and interface.</p><pre>def draw_detections(img, detections):<br>    &quot;&quot;&quot;Draw bounding boxes and perform per-person PPE check&quot;&quot;&quot;<br>    persons = [d for d in detections if d[&quot;class_name&quot;] == person_class]<br>    ppes = [d for d in detections if d[&quot;class_name&quot;] == ppe_class]<br><br>    for det in detections:<br>        x1, y1, x2, y2 = det[&#39;box&#39;]<br>        cls = det[&#39;class_name&#39;]<br>        conf = det[&#39;confidence&#39;]<br><br>        if cls == person_class:<br>            color = (255, 255, 0)  # Cyan for person<br>        elif cls == ppe_class:<br>            color = (0, 255, 0)    # Green for PPE<br>        else:<br>            color = (0, 0, 255)    # Red for others<br><br>        cv2.rectangle(img, (x1, y1), (x2, y2), color, 2)<br>        cv2.putText(img, f&quot;{cls} {int(conf*100)}%&quot;, (x1, y1-10),<br>                    cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)<br></pre><p>Finally, I ran the object detection model on the camera output</p><pre>results = model.predict(img_display, conf=confidence_threshold, verbose=False)<br>detections = parse_yolo_results(results)<br>img_display = draw_detections(img_display, detections)</pre><p>In the future, I intend to link this to a magnetic lock system that only permits individuals when they are properly dressed.</p><p>I believe this can help reduce incidents in the workplace, as complacency tends to set in when there has been a lack of incidents.</p><p>This system can help keep workers “on their toes” as they will know that they will be denied access without putting on their PPE.</p><p>The system can also help monitor workers that take off their PPE after access has been granted. A safety officer can then radio that worker or the team to help prevent an incident</p><h3>I also believe that this <strong>system will not replace Safety Officers</strong> but will rather <strong>give them a bird’s eye view</strong> of the site. Enabling them to spot risks while absent or far away.</h3><p>THANK YOU FOR MAKING IT THIS FAR!!!!!!!!!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7aa787e0d1ef" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Business Insights with Artificial Intelligence]]></title>
            <link>https://medium.com/@calebepelle5/business-insights-8aa8ed793cac?source=rss-46c7ffd9b1b2------2</link>
            <guid isPermaLink="false">https://medium.com/p/8aa8ed793cac</guid>
            <dc:creator><![CDATA[Caleb Epelle]]></dc:creator>
            <pubDate>Mon, 27 Oct 2025 05:05:22 GMT</pubDate>
            <atom:updated>2025-10-27T17:55:06.821Z</atom:updated>
            <content:encoded><![CDATA[<p>I started a business a little while after I left school and I quickly found out how daunting it could be to please clients. So, I thought, “why not have AI help me with that?” and I did just that.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*EEH6wNAGSi45sEp1.jpg" /></figure><p>I set out to use sentiment analysis as a tool to identify 2 things</p><ol><li>What my clients LOVE <em>(things/standards to maintain and/or improve on)</em></li><li>What my clients HATE <em>(things/standards to eliminate and/or improve)</em></li></ol><p>For sample data, I scraped the data of a product on Jumia’s website using the Beautiful Soup library to get data like the “reviews”, “number of stars” and so on.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dGWqZNL75Amas4l9-QVyLg.png" /><figcaption>Excel spreadsheet of scraped data</figcaption></figure><p>On carrying out some Exploratory Data Analysis I discovered that the product I chose was a good product, BUT it still had room to improve.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/831/1*0F3Hc0KclzuyxLB535r5vw.png" /><figcaption>Image showing the distribution of product rating</figcaption></figure><p>Using the Natural Language ToolKit library, I began carrying out my sentiment analysis.</p><pre>example = (df[&quot;review&quot;][499]).lower()<br>print(example)<br><br>#output: it’s good sleek and works fine</pre><p>Computers can’t understand punctuations so i went on to tokenize the review. This basically breaks the sentence into it’s component words and punctuations and classifies each word to the Part-of-Speech such as:</p><p>PRP: personal Pronoun, JJ: Adjective and so on.</p><pre>tokens = nltk.word_tokenize(example)<br>tokens[:200]<br> <br># output: [&#39;it&#39;, &#39;&#39;&#39;, &#39;s&#39;, &#39;good&#39;, &#39;sleek&#39;, &#39;and&#39;, &#39;works&#39;, &#39;fine&#39;]<br><br>tagged = nltk.pos_tag(tokens)<br>tagged[:200]<br><br>&quot;&quot;&quot;<br>output: <br>[(&#39;it&#39;, &#39;PRP&#39;),<br> (&#39;’&#39;, &#39;VBZ&#39;),<br> (&#39;s&#39;, &#39;RB&#39;),<br> (&#39;good&#39;, &#39;JJ&#39;),<br> (&#39;sleek&#39;, &#39;NN&#39;),<br> (&#39;and&#39;, &#39;CC&#39;),<br> (&#39;works&#39;, &#39;VBZ&#39;),<br> (&#39;fine&#39;, &#39;JJ&#39;)<br>]<br>&quot;&quot;&quot;<br><br>entities = nltk.chunk.ne_chunk(tagged)<br>entities.pprint()<br><br>#output: (S it/PRP ’/VBZ s/RB good/JJ sleek/NN and/CC works/VBZ fine/JJ)</pre><p>Then using 3 methods; VADER, ROBERTA and TRANSFORMER, I was able to get the overall sentiment of the review. I settled on using the transformer model solely as I observed that it had the highest accuracy and was the fastest to use.</p><pre>from transformers import pipeline<br><br>sent_pipeline = pipeline(&quot;sentiment-analysis&quot;)<br><br>print(sent_pipeline(&#39;Power surge fried all my ports&#39;))<br>print(sent_pipeline(&#39;Power surge fried all my ports&#39;)[0])<br>print(sent_pipeline(&#39;Power surge fried all my ports&#39;)[0][&quot;label&quot;])<br><br>&quot;&quot;&quot;<br>output: [{&#39;label&#39;: &#39;NEGATIVE&#39;, &#39;score&#39;: 0.9846639037132263}]<br>{&#39;label&#39;: &#39;NEGATIVE&#39;, &#39;score&#39;: 0.9846639037132263}<br>NEGATIVE<br>&quot;&quot;&quot;<br><br># applying transformer pipeline to &quot;review&quot; column and making a new column for transformer output<br>results_df[&quot;transformer&quot;] =(results_df[&#39;review&#39;]).apply(lambda x: sent_pipeline(x)[0][&quot;label&quot;])<br>results_df<br><br># isolating transformer output, review and stars cloums<br>pipeline_df = results_df[[&quot;review&quot;, &quot;transformer&quot;, &quot;stars&quot;]]<br>pipeline_df<br></pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/622/1*51FqlFXzEvBBJBmUmro_Xw.jpeg" /><figcaption>Isolated transformer output</figcaption></figure><p>The next step was to isolate the positive and negative reviews in order to identify areas of improvement.</p><pre>#NEGATIVE REVIEWS<br>negatives = results_df[results_df[&quot;transformer&quot;] == &quot;NEGATIVE&quot;]<br><br>negatives = negatives[[&quot;Id&quot;, &quot;name&quot;, &quot;review&quot;, &quot;stars&quot;, &quot;transformer&quot;]]<br>negatives<br><br>#POSITIVE REVIEWS<br>positives= results_df[results_df[&quot;transformer&quot;] == &quot;POSITIVE&quot;]<br><br>positives = positives[[&quot;Id&quot;, &quot;name&quot;, &quot;review&quot;, &quot;stars&quot;, &quot;transformer&quot;]]<br>positives</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/721/1*ItMDdezMk3RX2c1VWQfplA.png" /><figcaption>Negative reviews</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/737/1*SM0ot6hMFS-FDQNE__OanA.png" /><figcaption>Positive reviews</figcaption></figure><p>I then made a spreadsheet with the sentiments and reviews and a filter function. This made it easy for users who may not be Data Analyst sto share and utilize this data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*sE-ZDkglRQkX9BGQSH-d-w.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zdjNp5GnZ45UZpaO4snccw.png" /><figcaption>Negative and Positive filters being used in spreadsheet</figcaption></figure><p>This spreadsheet would help provide actionable insight into the pain points of product users.</p><p><strong>CONCLUSION</strong></p><p>Businesses can streamline their progress and growth as well as make themselves more efficient by using Artificial Intelligence in the form of Sentiment Analysis.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8aa8ed793cac" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Price Prediction of the Financial Markets]]></title>
            <link>https://medium.com/@calebepelle5/price-prediction-of-the-financial-markets-09b44fa5a509?source=rss-46c7ffd9b1b2------2</link>
            <guid isPermaLink="false">https://medium.com/p/09b44fa5a509</guid>
            <dc:creator><![CDATA[Caleb Epelle]]></dc:creator>
            <pubDate>Mon, 27 Oct 2025 05:04:24 GMT</pubDate>
            <atom:updated>2025-11-04T07:19:42.070Z</atom:updated>
            <content:encoded><![CDATA[<p>In 2020, I learned how to trade the forex markets, and in 2024, I left my job to develop my skills in machine learning. Along the line I found myself in need of money, so I fell back on what I knew about the forex market and started trading. As my knowledge and skill in machine learning grew, I thought to myself:<br>“Why not let the computer do this?”</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*6Bm4IMukBipyrmN_" /></figure><p>So, I did</p><p>and it was quite the journey.</p><p>I was able to achieve a system capable of predicting the price of an asset 1 day in advance <em>(with some degree of error of course)</em></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DiZ7ZHj4IZq0Mc70ZjLcfw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Vv3CehKNNHbWudHJ421mnA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*R03Vcw4A16bSipK7SYHc-A.png" /><figcaption>Prediction of price data 1 day prior (28/10/2025 7:01pm), 1 day after (29/10/2025 5:54pm) and 1 week after (04/11/2025 8:11am)</figcaption></figure><p>The first picture above shows the real time price in green with the predicted price in black. The prediction indicated that the price of the asset would go down by the next day.</p><p>The second picture shows that the real time price in green actually did go down <em>(although not to the degree indicated by the prediction), </em>it would still be able to give an individual a directional bias for the day ahead or even some form of directive on what action to take in the present <em>(whether to buy, sell or wait).</em></p><p>The third picture shows that the real time price in green actually did go down well beyond the initial prediction <em>(to a degree that surprised even me)</em></p><p>However, the model did not start out this way.</p><p>When I started, I had the <em>strangest </em>results</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ajm6da_eBnokqDYKytEJRw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*eWULfdTrWiJbMeDrW-_BEw.png" /><figcaption>Noisy Predictions</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*H4DzssEdxclewT4aEQuYIw.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*T7vENu-gLaqk-DgBEk2r6Q.png" /><figcaption>Noisy Predictions</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*B0lcprlSdsiS4efXSNnIvA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bvsHUpUJ47h3hvzKzRDDWw.png" /><figcaption>Noisy Predictions</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vw9PPJrQ3mKvmjjpISIQYg.png" /><figcaption>Noisy Predictions</figcaption></figure><p>These results sent me down a spiral of variable manipulations and loops to automate the process of variable manipulation to be able to find the best set of variables and hyperparameters to accomplish this task.</p><p>In the end I had a bit of an epiphany.</p><p>I set out to improve 2 things:</p><ol><li>Increase the memory of the system</li><li>Reduce the prediction timeline to 1 point ahead</li></ol><p>The previous models had poor memory and would try to predict up to 100 points into the future. This made them decompose or repeat previous predictions which led to decomposition and failure.</p><p>After accomplishing these 2 things, I was finally able to achieve the results I showed at first.</p><p>I learnt a few things from this project:</p><ol><li>Sometimes less is more</li><li>Never give up</li></ol><p><em>note: the code for this endeavor is kept private for specific reasons</em></p><p><strong><em>Thank you for reading this far!</em></strong></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=09b44fa5a509" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Effortless Attendance Tracking: Facial Recognition & Excel Insights]]></title>
            <link>https://medium.com/@calebepelle5/effortless-attendance-tracking-facial-recognition-excel-insights-843022573cf3?source=rss-46c7ffd9b1b2------2</link>
            <guid isPermaLink="false">https://medium.com/p/843022573cf3</guid>
            <dc:creator><![CDATA[Caleb Epelle]]></dc:creator>
            <pubDate>Mon, 27 Oct 2025 02:59:39 GMT</pubDate>
            <atom:updated>2025-10-27T04:58:36.221Z</atom:updated>
            <content:encoded><![CDATA[<h3>Project</h3><p>Creating a sign-in/attendance system that uses facial recognition to know the attendance of people and then autonomously log this attendance data into an excel spreadsheet daily. The excel spreadsheet then uses charts to track individual attendance performance by visual representation of the data.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*rhk8EmEOWN7tENAbdj9nVA.jpeg" /></figure><h3>Inspiration:</h3><p>I got this idea when i was in a meeting and i noticed someone having to write down the names of people who were in attendance. I thought it would be more effective to have an automated way of taking this attendance and tracking individuals to know their consistency per season.</p><h3>DESIGN STEPS</h3><ol><li>Webcam Display on Background</li><li>Create Database</li><li>Get Facial Landmark Encodings of Database Specimen</li><li>Compare Facial Landmark Encodings of Database Specimen with that from Webcam</li><li>Display Individual</li><li>Update Excel Spreadsheet</li><li>Visualize Data</li></ol><h3>THE CODE</h3><p><strong>STEP 1: WEBCAM DISPLAY ON BACKGROUND</strong></p><p>First thing that had to be done was to add a background image and create 2 sections on this background image: one for my live video output and the other for the image that would be displayed on facial recognition. (this code was written using python, using the computer camera as the video source)</p><pre># image/display set up<br>while True:<br>    success, img = cap.read()<br><br>    img_small = cv2.resize(img, (0,0), None, 0.25, 0.25)#scales image down to 1/4th the original size to reduce computational power<br>    img_small = cv2.cvtColor(img_small, cv2.COLOR_BGR2RGB)<br><br>    face_current_frame = face_recognition.face_locations(img_small)#picks out only the face in the video<br>    encode_currrent_frame = face_recognition.face_encodings(img_small,face_current_frame)#does encodings on face from camera<br><br>    if face_current_frame == []:<br>        img_background = cv2.imread(&quot;C:/Users/USER/Desktop/CHECK2/resources/background1.png&quot;)  # [vertical,horizontal]says that the space defined should show the picture chosen<br>        img_background[100:100 + 512, 735:735 + 421] = cv2.resize(image_mode_list[3], dsize=(421, 512),interpolation=cv2.INTER_CUBIC)  # [vertical,horizontal]says that the space defined should show the picture chosen<br><br>    img_background[162:162+480, 55:55+640] = img #says that the space defined should show the webcam footage<br>    img_background[162:162+480, 55:55+640] = cv2.flip(img,1)#horizontal flip = 1, vertical flip = 0<br>    imgg = cv2.flip(img,1)<br><br>    cv2.imshow(&quot;background&quot;,img_background)<br><br>    if cv2.waitKey(1) &amp; 0xFF == ord(&#39;s&#39;):<br>        break</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tUqsnjyj8bvJATu8Yfa5ww.png" /><figcaption>Output showing live feed and section for confirmation image</figcaption></figure><p><strong>STEP 2: CREATE DATABASE</strong></p><p>A database of multiple people with different pictures of them was created so the encodings for their faces could be made <em>(these were taken with consent)</em>. The folders were named after each person to make it easy to update the database when adding new members.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cJMs3PgwBou2mjvpm2eCUQ.png" /><figcaption>Database for multiple people. (each folder has multiple images for each person)</figcaption></figure><p><strong>STEP 3: GET FACIAL LANDMARK ENCODINGS OF DATABASE SPECIMEN</strong></p><p>A function was made to be able to get the facial landmarks <em>(similar to a fingerprint for the face) </em>and save them to an encode file.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/474/0*1T1J4DOPm4W0aqS7" /><figcaption>Stock mage of facial landmarks</figcaption></figure><pre>def find_encodings(image_list):<br>    encode_list = []<br><br>    for img in image_list:<br>        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)<br>        encodings = face_recognition.face_encodings(img)<br>        if len(encodings) &gt; 0:<br>            encode_list.append(encodings[0])  # ✅ take the first face only<br>        else:<br>            print(&quot;No face found in one of the images, skipping.&quot;)<br><br>    for i, enc in enumerate(encode_list):<br>        print(&quot;TESTING ENCODE LIST&quot;)# OUTPUT: 0 &lt;class &#39;numpy.ndarray&#39;&gt; (128,)<br>        print(i, type(enc), enc.shape)<br><br>    return encode_list<br><br>print(&quot;ENCODING STARTED...&quot;)<br>encode_list_known = find_encodings(image_list)<br>print(&quot;ENCODE LIST KNOWN&quot;)<br>print(encode_list_known)<br>encode_list_known_with_IDs = [encode_list_known, worker_IDs]<br>print(&quot;ENCODE LIST KNOWN WITH IDs&quot;)<br>print(encode_list_known_with_IDs)<br><br>print(&quot;ENCODING COMPLETE&quot;)<br><br>file = open(&quot;C:/Users/USER/Desktop/CHECK2/venv/encodefilee.p&quot;, &#39;wb&#39;)<br><br>pickle.dump(encode_list_known_with_IDs, file)<br>file.close()<br>print(&quot;FILE SAVED&quot;)</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MNdpX6Q5RN11wyhehmnM5Q.png" /><figcaption>encoding file</figcaption></figure><p><strong>STEP 4: COMPARE FACIAL LANDMARK ENCODINGS OF DATABASE SPECIMEN WITH THAT OF WEBCAM</strong></p><p>The live feed was then used to get the facial landmark encodings of whoever is visible in the feed. The code then compares the live feed encodings with the encodings stored in the file to find the closest match.</p><pre># face matching section<br>for encode_face, face_location in zip(encode_currrent_frame, face_current_frame):<br>    matches = face_recognition.compare_faces(encode_list_known, encode_face)<br>    facee_distance = face_recognition.face_distance(encode_list_known, encode_face)#lower face distance gives best matches<br><br>    matches_index = np.argmin(facee_distance)#gives the index no. of which picture has the best match with face on camera<br>    matches_index_list.append(matches_index)<br><br>    if matches == False:<br>        pass<br><br>    if matches[matches_index]:<br>        ID = worker_IDs[matches_index]<br>        print(&quot;KNOWN FACE DETECTED&quot;)#<br>        print(&quot;ID: &quot;, worker_IDs[matches_index])# #gives the ID or name of the worker(that the image is saved as)<br>        time() # GIVES TIME OF DETECTION FOR LOGGING PURPOSES<br>        img_background[100:100 + 512, 735:735 + 421] = cv2.resize(image_worker_list[matches_index], dsize = (421,512), interpolation = cv2.INTER_CUBIC)  # [vertical,horizontal]says that the space defined should show the picture chosen<br></pre><p><strong>STEP 5: DISPLAY INDIVIDUAL</strong></p><p>After face has been matched to a face in the database, the ID photograph of the recognized person is displayed.</p><pre># face matching section<br>for encode_face, face_location in zip(encode_currrent_frame, face_current_frame):<br>    matches = face_recognition.compare_faces(encode_list_known, encode_face)<br>    facee_distance = face_recognition.face_distance(encode_list_known, encode_face)#lower face distance gives best matches<br><br>    matches_index = np.argmin(facee_distance)#gives the index no. of which picture has the best match with face on camera<br>    matches_index_list.append(matches_index)<br><br>    if matches == False:<br>        pass<br><br>    if matches[matches_index]:<br>        ID = worker_IDs[matches_index]<br>        print(&quot;KNOWN FACE DETECTED&quot;)#<br>        print(&quot;ID: &quot;, worker_IDs[matches_index])# #gives the ID or name of the worker(that the image is saved as)<br>        time() # GIVES TIME OF DETECTION FOR LOGGING PURPOSES<br>        img_background[100:100 + 512, 735:735 + 421] = cv2.resize(image_worker_list[matches_index], dsize = (421,512), interpolation = cv2.INTER_CUBIC)  # [vertical,horizontal]says that the space defined should show the picture chosen</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kj-PE3YJWq8oP3ixufUsug.png" /><figcaption>Database picture is displayed</figcaption></figure><p><strong>STEP 5: UPDATE EXCEL SPREADSHEET</strong></p><p>A spreadsheet that marks the absence and presence of an individual per day was made. This spreadsheet value would be updated to “1” when a face is detected and a sum of the values of present and absent days is gotten.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*1ujuBw19IszSEnPKhGAbQw.png" /><figcaption>spreadsheet for attendance showing the dispersion of attendance across individuals</figcaption></figure><pre><br>attendance_data = pd.read_excel(&#39;C:/Users/USER/Desktop/CHECK2/List1.xlsx&#39;)<br><br># making status of person in attendance to equal &quot;1&quot;<br>attendance_data.loc[[attendance_data[attendance_data.WORKER_NAME == ID].index[0]], [&#39;TODAY&#39;]] = 1<br><br>print(&quot;SPECIFIC DATA&quot;)<br>print(attendance_data[attendance_data.WORKER_NAME == ID])<br>print(attendance_data[attendance_data.WORKER_NAME == ID][&#39;TODAY&#39;])<br>print(attendance_data)<br><br># ***********************************************************************************************<br>attendance_data.loc[[attendance_data[attendance_data.WORKER_NAME == ID].index[0]], [&#39;PRESENT&#39;]] = (attendance_data.loc[[attendance_data[attendance_data.WORKER_NAME == ID].index[0]]]).iloc[:, 1:-3].sum(axis=1, numeric_only=True)<br>print(attendance_data)<br><br>print(&quot;no. of days:&quot;, num_of_days)<br>print(&quot;CALC:&quot;, (num_of_days - ((attendance_data.loc[[attendance_data[attendance_data.WORKER_NAME == ID].index[0]], [&#39;PRESENT&#39;]]))))<br>print(&quot;CALC1:&quot;, (num_of_days - ((attendance_data.loc[[attendance_data[attendance_data.WORKER_NAME == ID].index[0]], [&#39;PRESENT&#39;]]).iloc[0])))<br>calc = (num_of_days - ((attendance_data.loc[[attendance_data[attendance_data.WORKER_NAME == ID].index[0]], [&#39;PRESENT&#39;]]).iloc[0])).iloc[0]<br>print(&quot;test 1&quot;, (num_of_days - ((attendance_data.loc[[attendance_data[attendance_data.WORKER_NAME == ID].index[0]], [&#39;PRESENT&#39;]]).iloc[0])).iloc[0])<br><br>attendance_data.loc[[attendance_data[attendance_data.WORKER_NAME == ID].index[0]], [&#39;ABSENTT&#39;]] = calc<br>chart_data.loc[[chart_data[chart_data.WORKER_NAME == ID].index[0]], [&#39;ABSENTT&#39;]] = calc<br>chart_data.loc[[chart_data[chart_data.WORKER_NAME == ID].index[0]], [&#39;PRESENT&#39;]] = (attendance_data.loc[[attendance_data[attendance_data.WORKER_NAME == ID].index[0]]]).iloc[:, 1:-2].sum(axis=1, numeric_only=True)<br><br>new_attendance = attendance_data<br>new_attendance.to_excel(&#39;C:/Users/USER/Desktop/CHECK2/List1.xlsx&#39;, index=None)<br>print(attendance_data)<br>new_chart = chart_data<br>new_chart.to_excel(&#39;C:/Users/USER/Desktop/CHECK2/Chart1.xlsx&#39;, index=None)<br>print(chart_data)</pre><p><strong>STEP 6: VISUALIZE DATA</strong></p><p>A second spreadsheet is made from the values of the previous spreadsheet that will be used to make a chart for assessment.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*VbsUa78Gg8i027a7uyOJpA.png" /><figcaption>spreadsheet used for chart</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bfRwg0teuwHmJZpvGB8wbw.png" /><figcaption>chart made to assess attendance with a red dashed line to represent minimum requirement</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*djAULuQFHPe2NoIrB1v42Q.png" /><figcaption>second chart used for easier to assess visualization</figcaption></figure><h3>FINAL PRODUCT</h3><p>After all processes were completed, a fully autonomous attendance tracking system was built, capable of logging and visualizing attendance data.</p><p>Thank you for reading this far.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=843022573cf3" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[My Attempt at Algorithmic Trading]]></title>
            <link>https://medium.com/@calebepelle5/my-attempt-at-algorithmic-trading-04dd3cb63212?source=rss-46c7ffd9b1b2------2</link>
            <guid isPermaLink="false">https://medium.com/p/04dd3cb63212</guid>
            <dc:creator><![CDATA[Caleb Epelle]]></dc:creator>
            <pubDate>Mon, 08 Sep 2025 18:11:14 GMT</pubDate>
            <atom:updated>2025-10-29T08:12:00.620Z</atom:updated>
            <content:encoded><![CDATA[<p>I started Learning to trade the forex markets in 2020, and in 2024, I left my job to develop skills in machine learning in an attempt to get into a new field of work.</p><p>One day, on my self development journey, I thought to myself:</p><p>&quot;why not combine these two things&quot;</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*kiVa3bSceqvV8LCJ9ZlZ1Q.jpeg" /></figure><p>So I did</p><p>and</p><p>Here are my results</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/720/1*MJm3gcgZcQPGNmvCiW4QWw.jpeg" /><figcaption>1 Month Trading Report</figcaption></figure><p>In the short space of a month I had <strong>increased my initial deposit by</strong> <strong>76%, moving my balance from $500 to $880.</strong><br>(<em>The code for this endeavor is kept private for specific reasons</em>).</p><p>But this was just the initial testing phase.<br>I kept going.<br>I kept testing my model on days and weeks and months and years worth of data from the forex markets.<br>I even made models to predict future prices to help in my manual trading(<em>post coming soon</em>).</p><p>But.</p><p>The more data I tested it on,<br>The worse the results got.</p><p>Either little to no gain was made or the model accrued losses and eventually lost the capacity to trade.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*LAsaXotouN_aWIBwxL5xXQ.png" /><figcaption>A ranging account balance before a sudden loss</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*XQ3CMSfs7QzNPRePDDgtAw.png" /><figcaption>A continuously decreasing account balance</figcaption></figure><p>At one point in time, the model was so bad that it even managed to achieve an exponentially decreasing account balance.</p><p>But these setbacks didn’t shake me.<br>I had seen positive results on less data, so I knew I could get positive results on more data.<br>I just needed to fine tune my model</p><p>And then, I got it.</p><p>An exponentially increasing model</p><p>I was able to achieve a <strong>profit of 154% , increasing my deposit of $500 to $1270 in the time span of 6 months. Averaging about 25% each month.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gtPyLu0NRqjcua6BVNwg3w.png" /><figcaption>Exponentially increasing account balance</figcaption></figure><p>What I learnt from this was the crucial parts of data science and machine learning :<br>1. Understanding and Knowing how to work with and manipulate data<br>2. Analyzing data</p><p>3. Understanding problems<br>4. Working through problems<br>5. Never giving up</p><p><em>note: the model still has its drawbacks. It is still being finetuned to achieve more optimal results.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=04dd3cb63212" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>