<?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"><channel><title><![CDATA[TheGradient.io - Learn, Code, Publish! Nothing can beat experiential learning]]></title><description><![CDATA[We cover the entire education cycle in Machine Learning and Data Science – that is: Learn, Code, Publish! Nothing can beat hands-on learning. Want to become proficient? Let's delve into it together.]]></description><link>https://thegradient.io</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1708080459492/Z881XUM68.png</url><title>TheGradient.io - Learn, Code, Publish! Nothing can beat experiential learning</title><link>https://thegradient.io</link></image><generator>RSS for Node</generator><lastBuildDate>Fri, 15 May 2026 04:08:13 GMT</lastBuildDate><atom:link href="https://thegradient.io/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Summary of Google Workspace Studio Release]]></title><description><![CDATA[Google has officially released Workspace Studio, a no-code platform that allows teams to build, manage, and deploy AI-powered agents across Gmail, Drive, Chat, and other Workspace tools. Even non-technical users can create intelligent workflows and a...]]></description><link>https://thegradient.io/summary-of-google-workspace-studio-release</link><guid isPermaLink="true">https://thegradient.io/summary-of-google-workspace-studio-release</guid><category><![CDATA[Google]]></category><category><![CDATA[gemini]]></category><dc:creator><![CDATA[Mohsen Davarynejad]]></dc:creator><pubDate>Tue, 09 Dec 2025 04:09:38 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1765253034454/665a8660-233b-4d78-a59e-9bbae10edef4.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Google has officially released <strong>Workspace Studio</strong>, a no-code platform that allows teams to build, manage, and deploy AI-powered agents across Gmail, Drive, Chat, and other Workspace tools. Even non-technical users can create intelligent workflows and automations using <strong>Gemini 3-powered agents</strong>.<br />Full article: <a target="_blank" href="https://eiai.today/news/google-released-workspace-studio?utm_source=chatgpt.com">https://eiai.today/news/google-released-workspace-studio</a></p>
<p>Early users report major productivity gains. In the <strong>Gemini Alpha</strong> phase, more than <strong>20 million tasks</strong> were completed through custom agents, and companies like <strong>Kärcher</strong> saw document-drafting time drop by <strong>90%</strong> — from hours to minutes.</p>
<p>These agents can analyze documents, summarize email threads, coordinate workflows, and connect with external tools like <strong>Asana, Jira, Salesforce, and Mailchimp</strong>.</p>
<p>The rollout has begun for <strong>Rapid Release</strong> domains, while <strong>Scheduled Release</strong> customers will gradually receive access starting <strong>January 5, 2026</strong>.</p>
<p>Release info: <a target="_blank" href="https://eiai.today/news/google-released-workspace-studio?utm_source=chatgpt.com">https://eiai.today/news/google-released-workspace-studio</a></p>
]]></content:encoded></item><item><title><![CDATA[Elon Musk’s Email Experiment: Can AI Unlock Workplace Productivity?]]></title><description><![CDATA[When Elon Musk challenged federal employees to list their top five responsibilities, the response was overwhelming; over a million emails flooded in. The sheer volume of data presented a significant challenge, but AI proved to be the key to making se...]]></description><link>https://thegradient.io/elon-musks-email-experiment-can-ai-unlock-workplace-productivity</link><guid isPermaLink="true">https://thegradient.io/elon-musks-email-experiment-can-ai-unlock-workplace-productivity</guid><category><![CDATA[Million Emails]]></category><category><![CDATA[agentic AI]]></category><category><![CDATA[agentic workflow]]></category><category><![CDATA[elon musk]]></category><dc:creator><![CDATA[Mohsen Davarynejad]]></dc:creator><pubDate>Thu, 06 Mar 2025 07:43:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1741246773019/33fc7c3d-016c-4e3c-bd38-21b0962d133c.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When Elon Musk challenged federal employees to list their top five responsibilities, the response was overwhelming; over a million emails flooded in. The sheer volume of data presented a significant challenge, but AI proved to be the key to making sense of the chaos.</p>
<p>By leveraging Large Language Models (LLMs) and Agentic AI, we uncovered patterns in workplace efficiency, accountability, and organizational bottlenecks. The results? AI-powered analysis can reveal hidden productivity trends, employee engagement levels, and operational inefficiencies across large-scale enterprises.</p>
<p>🔍 <strong>How does AI cut through the noise?</strong> Our latest deep dive explores how CrewAI can be used to extract structured insights from unstructured email data. Using intelligent agent workflows, we demonstrate how AI can categorize responses, conduct sentiment analysis, and pinpoint inefficiencies, at scale.</p>
<p>📖 Read the full breakdown here: <a target="_blank" href="https://dataqubed.io/blog/agentic-ai/agentic-ai-and-deepseek-decoding-a-million-emails/">https://dataqubed.io/blog/agentic-ai/agentic-ai-and-deepseek-decoding-a-million-emails/</a></p>
<p>#AI #Productivity #AgenticAI #DataAnalysis #ElonMusk</p>
]]></content:encoded></item><item><title><![CDATA[Demystifying the Black Box: A Guide to Interpretable and Explainable AI Models]]></title><description><![CDATA[Artificial Intelligence (AI) has made remarkable strides in recent years, transforming different industries and enabling machines to make complex decisions. However, the inner workings of AI models have often been regarded as "black boxes," raising c...]]></description><link>https://thegradient.io/demystifying-the-black-box-a-guide-to-interpretable-and-explainable-ai-models</link><guid isPermaLink="true">https://thegradient.io/demystifying-the-black-box-a-guide-to-interpretable-and-explainable-ai-models</guid><category><![CDATA[AI]]></category><category><![CDATA[Black box]]></category><category><![CDATA[Data Integrity]]></category><category><![CDATA[neural networks]]></category><dc:creator><![CDATA[Isaac Onyeakagbu]]></dc:creator><pubDate>Wed, 21 Feb 2024 04:12:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1708450806619/23113d2b-9417-47f5-951c-a16dab6177d6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Artificial Intelligence (AI) has made remarkable strides in recent years, transforming different industries and enabling machines to make complex decisions. However, the inner workings of AI models have often been regarded as "black boxes," raising concerns about their transparency and trustworthiness. In this article, we'll unravel the mysteries of black box AI models and introduce you to interpretable and explainable AI techniques. We'll provide some code examples in Python to make the concepts tangible.</p>
<p>Let’s dive in.</p>
<h1 id="heading-understanding-the-black-box"><strong>Understanding the Black Box</strong></h1>
<p>AI models, particularly deep learning models like neural networks, are often perceived as black boxes due to their complex architectures and the opacity of their decision-making processes. These models learn from data, but understanding why they make specific predictions can be challenging.</p>
<h2 id="heading-what-is-interpretability-and-why-does-it-matter">What is Interpretability and Why Does it Matter?</h2>
<p>Interpretability is the ability to understand and explain how a model arrives at a particular prediction. Explainability provides transparency into the reasoning and internal logic behind AI systems. But why does interpretability matter?</p>
<ul>
<li><p>Trustworthiness - Users must trust systems to adopt them. Complex models like deep learning can behave as black boxes, making errors mysterious. Explainability builds user trust in model behaviors.</p>
</li>
<li><p>Ethics and Fairness - AI systems must avoid perpetuating historical biases or discrimination. Interpretability allows auditing for fairness. The EU’s GDPR grants users the right to explanations for algorithmic decisions affecting them.</p>
</li>
<li><p>Legal Compliance and Adoption - Regulations increasingly demand explanations of algorithmic systems. The US Federal Trade Commission may soon require explainability for certain AI applications. Interpretability is key for ethical, compliant adoption.</p>
</li>
<li><p>Debugging and Improvement - Insights from interpretable models can reveal and prevent errors, improving performance. Explanations can identify weakly modeled areas needing more training data.</p>
</li>
</ul>
<h1 id="heading-interpretable-ai-models">Interpretable AI Models</h1>
<p>Let's start by exploring interpretable AI models that are easy to understand and analyze.</p>
<h2 id="heading-linear-regression">Linear Regression</h2>
<p>Linear regression is one of the simplest and most interpretable machine learning models. It models a linear relationship between input features and the target variable. Here's a Python code example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">from</span> sklearn.linear_model <span class="hljs-keyword">import</span> LinearRegression

<span class="hljs-comment"># Sample data</span>
X = np.array([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]).reshape(<span class="hljs-number">-1</span>, <span class="hljs-number">1</span>)
y = np.array([<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>])

<span class="hljs-comment"># Create and fit the model</span>
model = LinearRegression()
model.fit(X, y)

<span class="hljs-comment"># Get coefficients</span>
slope = model.coef_[<span class="hljs-number">0</span>]
intercept = model.intercept_

print(<span class="hljs-string">f"Slope: <span class="hljs-subst">{slope}</span>, Intercept: <span class="hljs-subst">{intercept}</span>"</span>)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695211767143/e37e3e70-a2a3-4c1a-b841-9f47c38ce28a.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-decision-trees">Decision Trees</h2>
<p>Decision trees are another interpretable model. They make predictions by following a tree-like structure of decisions. Visualizing a decision tree can help understand its decision-making process:</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> sklearn.tree <span class="hljs-keyword">import</span> DecisionTreeClassifier, plot_tree
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-comment"># Sample data</span>
X = [[<span class="hljs-number">0</span>, <span class="hljs-number">0</span>], [<span class="hljs-number">1</span>, <span class="hljs-number">1</span>]]
y = [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>]

<span class="hljs-comment"># Create and fit the model</span>
model = DecisionTreeClassifier()
model.fit(X, y)

<span class="hljs-comment"># Visualize the decision tree</span>
plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">5</span>))
plot_tree(model, filled=<span class="hljs-literal">True</span>, feature_names=[<span class="hljs-string">"Feature 1"</span>, <span class="hljs-string">"Feature 2"</span>])
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695211934211/471d2821-0cc9-43e2-92e7-f5f5760ee5b6.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-explainable-ai-models">Explainable AI Models</h1>
<p>Now, let's explore explainable AI models that shed light on black box models' predictions.</p>
<h2 id="heading-lime-local-interpretable-model-agnostic-explanations">LIME (Local Interpretable Model-Agnostic Explanations)</h2>
<p>LIME is a powerful tool for explaining the predictions of complex models. It works by training a locally interpretable model on a dataset generated around the instance of interest. Here's a Python example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> lime
<span class="hljs-keyword">import</span> lime.lime_tabular
<span class="hljs-keyword">from</span> sklearn.linear_model <span class="hljs-keyword">import</span> LogisticRegression
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Sample data for Logistic Regression (2 features)</span>
X_logistic = np.array([[<span class="hljs-number">0</span>, <span class="hljs-number">0</span>], [<span class="hljs-number">1</span>, <span class="hljs-number">1</span>], [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>], [<span class="hljs-number">1</span>, <span class="hljs-number">0</span>]])
y_logistic = np.array([<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>])

<span class="hljs-comment"># Create and fit the Logistic Regression model</span>
logistic_model = LogisticRegression()
logistic_model.fit(X_logistic, y_logistic)

<span class="hljs-comment"># Sample data for LIME explanation (2 features)</span>
X_lime = np.array([[<span class="hljs-number">0</span>, <span class="hljs-number">0</span>]])  <span class="hljs-comment"># Replace with your data</span>

<span class="hljs-comment"># Create a LIME explainer</span>
explainer = lime.lime_tabular.LimeTabularExplainer(X_logistic, mode=<span class="hljs-string">"classification"</span>)

<span class="hljs-comment"># Explain a specific prediction (e.g., the first data point)</span>
explanation = explainer.explain_instance(X_lime[<span class="hljs-number">0</span>], logistic_model.predict_proba)

explanation.show_in_notebook()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695214286141/f29cf1ea-34fb-4eb5-ab9f-893fe4e25c6e.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-shap-shapley-additive-explanations">SHAP (SHapley Additive exPlanations)</h2>
<p>SHAP values are rooted in game theory and provide a unified measure of feature importance for any model. They can be used to explain both global and individual predictions:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> shap

<span class="hljs-comment"># Create an explainer</span>
explainer = shap.Explainer(model, X)
shap_values = explainer(X)

<span class="hljs-comment"># Visualize the SHAP values</span>
shap.summary_plot(shap_values, X)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695216293287/8c9636e8-1ac9-4702-9943-4d93a0dd078d.gif" alt class="image--center mx-auto" /></p>
<h1 id="heading-building-interpretable-neural-networks">Building Interpretable Neural Networks</h1>
<p>Neural networks, despite being black boxes, can be made more interpretable.</p>
<h2 id="heading-saliency-maps">Saliency Maps</h2>
<p>Saliency maps highlight regions of an input image that influence a neural network's decision. Below is a Python code snippet using TensorFlow/Keras:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> tensorflow <span class="hljs-keyword">as</span> tf
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

model = tf.keras.applications.MobileNetV2(weights=<span class="hljs-string">"imagenet"</span>)

<span class="hljs-comment"># Load an image</span>
image = tf.keras.preprocessing.image.load_img(<span class="hljs-string">"cat.jpg"</span>, target_size=(<span class="hljs-number">224</span>, <span class="hljs-number">224</span>))
input_image = tf.keras.preprocessing.image.img_to_array(image)
input_image /= <span class="hljs-number">255.0</span>

<span class="hljs-comment"># Compute the gradients (saliency map)</span>
<span class="hljs-keyword">with</span> tf.GradientTape() <span class="hljs-keyword">as</span> tape:
    inputs = tf.convert_to_tensor(input_image[tf.newaxis, ...], dtype=tf.float32)
    tape.watch(inputs)
    predictions = model(inputs)
    top_prediction = tf.argmax(predictions[<span class="hljs-number">0</span>])
    gradient = tape.gradient(predictions[:, top_prediction], inputs)
    gradient = gradient / np.max(np.abs(gradient)) 
gradient = (gradient + <span class="hljs-number">1</span>) / <span class="hljs-number">2</span> <span class="hljs-comment"># shift range from [-1, 1] to [0, 1]</span>

<span class="hljs-comment"># Plot the saliency map</span>
plt.imshow(gradient[<span class="hljs-number">0</span>])
plt.axis(<span class="hljs-string">'off'</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695223244683/5389243f-1e00-4d5c-99b1-ccbd20546f2e.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-feature-importance-in-neural-networks">Feature Importance in Neural Networks</h2>
<p>You can assess feature importance in neural networks using gradient-based methods or feature occlusion. Here's a code snippet using gradient-based feature importance:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> tensorflow <span class="hljs-keyword">as</span> tf
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">load_dataset</span>():</span>
  num_samples = <span class="hljs-number">1000</span>
  num_features = <span class="hljs-number">4</span>

  X = np.random.rand(num_samples, num_features)
  y = np.random.randint(<span class="hljs-number">0</span>, <span class="hljs-number">3</span>, size=num_samples)

  <span class="hljs-keyword">return</span> X, y

X_train, y_train = load_dataset()

<span class="hljs-comment"># Convert NumPy array to TF tensor</span>
X_train = tf.convert_to_tensor(X_train)

model = tf.keras.Sequential([
  tf.keras.layers.Dense(<span class="hljs-number">128</span>, activation=<span class="hljs-string">'relu'</span>, input_shape=(<span class="hljs-number">4</span>,)), 
  tf.keras.layers.Dense(<span class="hljs-number">64</span>, activation=<span class="hljs-string">'relu'</span>),
  tf.keras.layers.Dense(<span class="hljs-number">3</span>, activation=<span class="hljs-string">'softmax'</span>)
])

model.compile(
  optimizer=<span class="hljs-string">'adam'</span>,
  loss=<span class="hljs-string">'sparse_categorical_crossentropy'</span>,
  metrics=[<span class="hljs-string">'accuracy'</span>]
)

model.fit(X_train, y_train, epochs=<span class="hljs-number">10</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">gradient_feature_importance</span>(<span class="hljs-params">model, inputs, class_index</span>):</span>
  <span class="hljs-keyword">with</span> tf.GradientTape() <span class="hljs-keyword">as</span> tape:
    tape.watch(inputs)
    predictions = model(inputs)
    loss = predictions[:, class_index]

  gradient = tape.gradient(loss, inputs) 
  feature_importance = tf.reduce_mean(tf.abs(gradient), axis=<span class="hljs-number">0</span>)

  <span class="hljs-keyword">return</span> feature_importance.numpy()

class_index = <span class="hljs-number">0</span>
feature_importance = gradient_feature_importance(model, X_train, class_index)

plt.bar(range(len(feature_importance)), feature_importance)
plt.xlabel(<span class="hljs-string">'Feature Index'</span>)
plt.ylabel(<span class="hljs-string">'Feature Importance'</span>)
plt.show()
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695224651720/c99a51ae-38fb-4689-87eb-872b25071fee.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1695224674129/b2812a3c-4d9b-4b87-af37-b4a274403f84.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-ethical-considerations">Ethical Considerations</h1>
<p>As AI interpretability and explainability are vital, we must also consider ethical aspects:</p>
<h2 id="heading-fairness-and-bias">Fairness and Bias</h2>
<p>AI models can inherit biases present in training data. To detect and mitigate bias, you can use libraries like AIF360 or Fairlearn in Python.</p>
<p>Below is a code snippet using AIF360</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">from</span> aif360.datasets <span class="hljs-keyword">import</span> BinaryLabelDataset  
<span class="hljs-keyword">from</span> aif360.metrics <span class="hljs-keyword">import</span> BinaryLabelDatasetMetric
<span class="hljs-keyword">from</span> aif360.algorithms.preprocessing <span class="hljs-keyword">import</span> Reweighing

<span class="hljs-comment"># Create sample biased dataset</span>
data = {<span class="hljs-string">'gender'</span>: [<span class="hljs-string">'male'</span>, <span class="hljs-string">'female'</span>, <span class="hljs-string">'female'</span>, <span class="hljs-string">'male'</span>, <span class="hljs-string">'male'</span>],  
        <span class="hljs-string">'hired'</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>],
        <span class="hljs-string">'qualified'</span>: [<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>]}

df = pd.DataFrame(data)

<span class="hljs-comment"># Encode categorical columns  </span>
df[<span class="hljs-string">'gender'</span>] = df[<span class="hljs-string">'gender'</span>].map({<span class="hljs-string">'male'</span>: <span class="hljs-number">0</span>, <span class="hljs-string">'female'</span>: <span class="hljs-number">1</span>})

<span class="hljs-comment"># Convert to BinaryLabelDataset</span>
bl_data = BinaryLabelDataset(df=df, 
                             label_names=[<span class="hljs-string">'hired'</span>],
                             protected_attribute_names=[<span class="hljs-string">'gender'</span>],
                             favorable_label=<span class="hljs-number">1</span>,
                             unfavorable_label=<span class="hljs-number">0</span>)

<span class="hljs-comment"># Compute original bias metrics</span>
print(BinaryLabelDatasetMetric(bl_data, privileged_groups=[{<span class="hljs-string">'gender'</span>: <span class="hljs-number">1</span>}], unprivileged_groups=[{<span class="hljs-string">'gender'</span>: <span class="hljs-number">0</span>}]))

<span class="hljs-comment"># Mitigate bias using reweighing</span>
RW = Reweighing(unprivileged_groups=[{<span class="hljs-string">'gender'</span>: <span class="hljs-number">0</span>}], privileged_groups=[{<span class="hljs-string">'gender'</span>: <span class="hljs-number">1</span>}])
rw_data = RW.fit_transform(bl_data)

<span class="hljs-comment"># Compute bias metrics after reweighing </span>
print(BinaryLabelDatasetMetric(rw_data, privileged_groups=[{<span class="hljs-string">'gender'</span>: <span class="hljs-number">1</span>}], unprivileged_groups=[{<span class="hljs-string">'gender'</span>: <span class="hljs-number">0</span>}]))
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1696083372544/84d8a92d-6d48-44b3-aeb9-ee7e13b4e418.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-best-practices-for-model-interpretability">Best Practices for Model Interpretability</h1>
<p>To ensure model interpretability in practice, follow these best practices:</p>
<h2 id="heading-model-documentation">Model Documentation</h2>
<p>Documenting your model is essential for transparency and collaboration. Here are some key components to include in your model documentation:</p>
<ul>
<li><p>Model Architecture: Describe the structure of your model, including the type and number of layers, activation functions, and any regularization techniques used.</p>
</li>
<li><p>Hyperparameters: List the hyperparameters used during model training, such as learning rate, batch size, and dropout rate.</p>
</li>
<li><p>Training Data: Specify the dataset used for training, including data sources, preprocessing steps, and any data augmentation techniques applied.</p>
</li>
<li><p>Performance Metrics: Report the evaluation metrics used to assess your model's performance, such as accuracy, precision, recall, and F1-score.</p>
</li>
<li><p>Interpretability Techniques: Document the interpretable techniques employed, such as LIME, SHAP, or saliency maps.</p>
</li>
<li><p>Bias Assessment: If applicable, describe how you assessed and addressed bias in your model.</p>
</li>
<li><p>Results: Provide results and insights gained from model interpretation, including any actionable recommendations.</p>
</li>
</ul>
<h2 id="heading-model-selection">Model Selection</h2>
<p>When choosing a model for your AI application, consider the trade-offs between complexity and interpretability. Here are some guidelines:</p>
<ul>
<li><p>Start Simple: If interpretability is a top priority, begin with simpler models like linear regression or decision trees.</p>
</li>
<li><p>Evaluate Trade-offs: Assess the balance between model accuracy and interpretability. Sometimes, a slightly less accurate but more interpretable model is preferred.</p>
</li>
<li><p>Ensemble Models: Ensemble techniques like random forests can provide a compromise between accuracy and interpretability by combining multiple decision trees.</p>
</li>
<li><p>Regularization: Use regularization techniques (e.g., L1 regularization) to promote sparsity in neural networks, making them more interpretable.</p>
</li>
</ul>
<h1 id="heading-the-future-outlook">The Future Outlook</h1>
<p>Explainable AI adoption will likely accelerate due to growing calls for accountability. Techniques to generate explanations must continue evolving beyond simple attention layers or feature attribution methods. The ultimate goal is demystifying even the most complex black box models.</p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>In this guide, we've demystified the black-box nature of AI models by introducing you to interpretable and explainable AI techniques.</p>
<p>Interpretable and explainable AI models are crucial for building trustworthy and ethical AI systems. By following best practices, documenting your models, and being mindful of ethical considerations, you can harness the power of AI while maintaining transparency and accountability.</p>
]]></content:encoded></item><item><title><![CDATA[The Future of Fitness Industry: Innovative Trends, Community Challenges, and Opportunities]]></title><description><![CDATA[Introduction
I have been looking into ways to leverage the capabilities of LLMs in the fitness industry. And here we have it. The following few paragraphs are the result of feeding ChatGPT-4 through API calls with relevant information gathered from s...]]></description><link>https://thegradient.io/the-future-of-fitness-industry-innovative-trends-community-challenges-and-opportunities</link><guid isPermaLink="true">https://thegradient.io/the-future-of-fitness-industry-innovative-trends-community-challenges-and-opportunities</guid><category><![CDATA[llm]]></category><category><![CDATA[langchain]]></category><category><![CDATA[openai]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Mohsen Davarynejad]]></dc:creator><pubDate>Tue, 13 Feb 2024 10:40:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1707820679833/b3aebd25-a2cb-46b7-b79e-e399a41dbd4b.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>I have been looking into ways to leverage the capabilities of LLMs in the fitness industry. And here we have it. The following few paragraphs are the result of feeding ChatGPT-4 through API calls with relevant information gathered from some Reddit posts and asking it to make a blog post out of it. All this is made possible by constructing a few Agents and defining the specific Tasks for them. In a forthcoming follow-up post, I will provide the full detailed process of how to get there. I shall provide an in-depth look at how Python, along with LangChain and LangGraph (to leverage the concept of agents and tasks) can be harnessed to generate insights that drive innovation in fitness and beyond. Stay tuned for a comprehensive guide that will showcase the potential of AI to transform our approach to wellness and community building.</p>
<h2 id="heading-the-future-of-fitness-industry-innovative-trends-community-challenges-and-opportunities">The Future of Fitness Industry: Innovative Trends, Community Challenges, and Opportunities</h2>
<p>In our progressively digital society, the fitness world is on a constant revolution. The most recent trends extracted from fitness discussions on Reddit underline the significance of well-structured exercise routines, balanced protein-rich diets, and the essentiality of resources for beginners.</p>
<h3 id="heading-innovative-fitness-trends"><strong>Innovative Fitness Trends</strong></h3>
<p>The fitness community is buzzing with more than just the latest High-Intensity Interval Training (HIIT) workout. A deep dive into online discussions unveils that structured exercise routines are the new norm. It's not just about hitting the gym anymore - it's about following a plan, setting goals, and tracking progress for optimum results.</p>
<p>Nutrition is equally vital in this journey. A balanced, protein-rich diet has emerged as a fundamental part of the fitness lifestyle. It's not just what you do in the gym, but also what you consume outside it that shapes your fitness story.</p>
<p>For fitness novices, the journey often seems overwhelming. The high demand for beginner-friendly resources is reflective of individuals seeking guidance on where to start and how to stay committed.</p>
<h3 id="heading-community-challenges"><strong>Community Challenges</strong></h3>
<p>However, every trend brings its own set of challenges. In the fitness community, one of the most prevalent hurdles is maintaining consistency. Upholding a regular diet and fitness routine is challenging, and it becomes even more demanding when life throws curveballs.</p>
<h3 id="heading-identifying-market-opportunities">Identifying Market Opportunities</h3>
<p>Our findings also disclose potential opportunities in the fitness market. Despite the abundance of resources available, there's a need for personalized diet and workout plans tailored to individual requirements and objectives. Another opportunity lies in creating beginner-friendly fitness resources. While the internet is flooded with information, not all of it is easy to understand or implement. Lastly, platforms that offer community support and motivation are in high demand.</p>
<h3 id="heading-the-path-ahead">The Path Ahead</h3>
<p>The fitness industry should take note of these insights. There's a chance to innovate by developing resources that not only educate beginners about fitness and nutrition but also mentor them and offer support to help them stay motivated.</p>
<p>By addressing these opportunities, we can encourage a supportive community environment, making the fitness journey less intimidating and more achievable. Whether you're a fitness novice or a seasoned pro, remember, your journey is unique, and the right resources can significantly impact your success.]</p>
<p>Stay connected for more insights and discussions from the rapidly evolving universe of fitness. Until next time, keep moving, keep fueling right, and keep aiming for your best self!</p>
<hr />
<p>The link to the follow-up post with detailed Python implementation will be provided here. So stay tuned!!</p>
<p>*Cover Image generated by DALL·E 3</p>
]]></content:encoded></item><item><title><![CDATA[Scala Tutorial by Example - Platform free]]></title><description><![CDATA[This is a gentle introduction to programming in Scala. This tutorial is still under active development. In case you happen to have an interest in completing the tutorial by providing your working example, then let's get connected.
Let's start by answ...]]></description><link>https://thegradient.io/scala-tutorial-by-example-platform-free</link><guid isPermaLink="true">https://thegradient.io/scala-tutorial-by-example-platform-free</guid><category><![CDATA[Scala]]></category><dc:creator><![CDATA[Mohsen Davarynejad]]></dc:creator><pubDate>Sun, 11 Feb 2024 20:17:06 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1707682196737/c4f685d8-86ae-44ff-b5e7-f4295561e19b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is a gentle introduction to programming in Scala. This tutorial is still under active development. In case you happen to have an interest in completing the tutorial by providing your working example, then let's get <a target="_blank" href="http://mohsen.thegradient.io">connected</a>.</p>
<p>Let's start by answering the question of why I want to learn Scala.</p>
<h2 id="heading-why-scala-the-real-drivers-for-getting-into-it"><strong>Why Scala? The real drivers for getting into it!</strong></h2>
<p>Scala is among the top 10 most popular programming languages. It helps you elegantly solve real-world problems in many ways. It allows you to combine the concepts of functional programming and object-oriented design.</p>
<p>The reasons there are so many high-profile Scala users, like Twitter and LinkedIn, eventually boil down to runtime performance and stability as well as the availability of libraries for building concurrent and distributed applications (using actors). In addition, Scala programming significantly cuts down the development time of an application and its maintenance expense.</p>
<p>If I want to go a bit more into detail, I would say that Scala encourages the usage of immutable data structures, making it more error-prone, safer, and perhaps easier to understand. Moreover, Scala runs on Java Virtual Machine (JVM) and it plays well with existing Java applications, meaning that a lot of libraries can be easily used with Scala. JVM is known for its monitoring, garbage collecting, and load balancing tools.</p>
<p>If you want to explore the world of functional programming then <code>Scala</code> is a perfect choice without completely disregarding the choice of object-oriented programming.</p>
<p><img src="https://web.archive.org/web/20200219220522im_/http://behsys.com/mohsen/images/Scala-hack.png" alt="scala for scala hackers" /></p>
<p><strong>Note:</strong> If you are new to the concept of functional programming, it is often recommended to start with Haskell, and play with it for a while. The point is that in Haskell, you cannot drift into non-functional programming. So perhaps you can do a quick but thorough brush-up to rewire your brain. The best place to practice some Haskell is <a target="_blank" href="http://learnyouahaskell.com/chapters">Learn You a Haskell for Great Good</a>!</p>
<p>For my tutorial, I will try to follow the structure presented <a target="_blank" href="http://learnyouahaskell.com/chapters">here</a>, but from time to time I may deviate from it. I will also borrow some of the nice visualizations presented there.</p>
<h2 id="heading-some-facts-about-scala"><strong>Some facts about Scala</strong></h2>
<p>• In Scala usage of semicolons is mandatory, and you need to use them only when you have multiple statements per line.</p>
<p>• Scala offers better concurrency by using immutability and actors. (I will make this point more clear as we go)</p>
<p>• Scala runs on both Java and. NET. For more info have a look <a target="_blank" href="https://www.infoq.com/news/2011/07/Scala.NET">here</a></p>
<p>Now let's jump right into the installation process.</p>
<h2 id="heading-installation"><strong>Installation</strong></h2>
<p>Let’s first try to install Scala on a Linux machine and set up a Jupiter notebook for IDE. The first thing we need to install or upgrade is JVM. So go to <a target="_blank" href="http://behsys.com/mohsen/www.java.com/en/download">www.java.com/en/download</a>. To install Java you may like to follow the instructions provided <a target="_blank" href="https://www.digitalocean.com/community/tutorials/how-to-install-java-on-centos-and-fedora">here</a>.</p>
<p>If you are on Mac, it’s pretty easy to install Scala. You need to go to brew.sh and install <code>Homebrew</code>. Now inside your terminal just type <code>$ brew install scala</code> and that’s it.</p>
<p>For Linux, you need to download the binaries and unpack the archive from <a target="_blank" href="https://web.archive.org/web/20200219220522/https://www.scala-lang.org/download/install.html">here</a>. Unpack the <code>.tar</code> file by <code>tar zxvf fileNameHere.tgz</code> . Then you need to add Scala and Scalac to your path by editing <code>.bashrc</code> .</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> SCALA_HOME=/home/cloudera/workspace/scala/scala-2.12.1/
<span class="hljs-built_in">export</span> PATH=<span class="hljs-variable">$SCALA_HOME</span>/bin:<span class="hljs-variable">$PATH</span>
</code></pre>
<p>The best choice for me is just to download a Cloudera VM. If you are a data scientist or if you just would like to start with data science and analytics then I would recommend you go and get one of the Cloudera VMs. It comes prepacked with most of the big data tools, like Hadoop, Hue, Hive, HBase, and Impala. Also, Scala is installed in it, where you can call spark jobs through Scala or Python APIs. If you have downloaded a Cloudera VM, then the only thing you need to do is just to type in <code>spark-shell</code>, and you are going to your first Scala project.</p>
<p>And now if you are interested in running your Scala application in Jupiter Notebook, follow the instructions <a target="_blank" href="https://developer.ibm.com/hadoop/2016/05/04/install-jupyter-notebook-spark/">here</a> on how to install Scala Kernel for Jupyter.</p>
<p>You may also like to use <a target="_blank" href="https://www.jetbrains.com/idea/">IntelliJ IDEA</a>, which I recommend if you are coding for a big Scala project.</p>
<p>OK, enough on the installation process and facts on Scala. Let’s begin with some coding.</p>
<h2 id="heading-basics-of-scala"><strong>Basics of Scala</strong></h2>
<p>Here I would like to start with some very basic codes in Scala, just to give you the feeling that Scala is a language that shares a lot of similarities with other languages. At the same time, I would to emphasize that Scala is a paradigm shift. We will cover the <a target="_blank" href="http://behsys.com/mohsen/Scala-Tutorial-Scala-by-Example.html#fundamentals-of-Scala">fundamentals of Scala</a> in another section.</p>
<pre><code class="lang-scala"><span class="hljs-comment">// This is the way to put comments on your code. You can put multiline comment by opening /* and closing */. This is similar to way we put comments in Java.</span>
<span class="hljs-comment">// Now let’s do some basic math. In your command line just type in</span>
<span class="hljs-number">2</span> + <span class="hljs-number">2</span> * <span class="hljs-number">2</span>
<span class="hljs-comment">// This will create a variable res0 with type Int and value of 6. Now you can used this res0 variable in the rest of your code.</span>
<span class="hljs-string">"The value of res0 is: "</span> + res0
<span class="hljs-comment">// And what you get in return is: res1: String = The value of res0 is: 4. So now not only we have the results, but the result is also store in a variable res1 with type String.</span>
<span class="hljs-comment">// Note that when a value is assigned to variable, it cannot be changed. So in you type in</span>
res0 = <span class="hljs-number">2</span>
<span class="hljs-comment">// Then you will get an error message, informing you that the value of the variable cannot be changed.</span>
<span class="hljs-comment">// If you need to define a variable that needs to be changed, then you need to use var.</span>
<span class="hljs-keyword">var</span> myMessage = <span class="hljs-string">"Make sure to import the necessary libraries."</span>
</code></pre>
<h3 id="heading-make-big-numbers"><strong>Make big numbers</strong></h3>
<p>Like all other programming languages, if you use big numbers, you will lose the precision. To prevent that you can use <code>BigDecimal</code> and <code>BigInt</code>.</p>
<pre><code class="lang-scala"><span class="hljs-keyword">var</span> myInt = <span class="hljs-type">BigInt</span>(<span class="hljs-string">"1234567890123456789012345678901234567890"</span>)
<span class="hljs-keyword">var</span> myDecimal = <span class="hljs-type">BigDecimal</span>(<span class="hljs-string">"10.1234567890123456789012345678901234567890"</span>)
</code></pre>
<h3 id="heading-generate-random-numbers-with-scala"><strong>Generate random numbers with Scala</strong></h3>
<p>To get a random number drawn from a uniform distribution bounded between 0 and one:</p>
<pre><code class="lang-scala">random
</code></pre>
<p>You can easily generate random inciter numbers between 0 and 6:</p>
<pre><code class="lang-scala">(random * <span class="hljs-number">6</span> + <span class="hljs-number">1</span>).toInt
</code></pre>
<h3 id="heading-some-math"><strong>Some Math</strong></h3>
<p>In Scala, you cannot do ++ or --. However, you can do the following:</p>
<pre><code class="lang-scala">myInt = <span class="hljs-number">12</span>
myInt += <span class="hljs-number">4</span>
myInt -= <span class="hljs-number">2</span>
myInt *= <span class="hljs-number">10</span>
</code></pre>
<p>First, let's import a library in Scala and do some simple math.</p>
<pre><code class="lang-scala"><span class="hljs-keyword">import</span> scala.math._
<span class="hljs-comment">// This will import all the</span>
abs(<span class="hljs-number">-1</span>) <span class="hljs-comment">// for abs value</span>
ceil(<span class="hljs-number">-1.2</span>)
round(<span class="hljs-number">-1.2</span>)
floor(<span class="hljs-number">-1.2</span>)
toRadians(<span class="hljs-number">45</span>)
toDegrees(<span class="hljs-number">0.78</span>)
sqrt(<span class="hljs-number">10</span>)
pow(<span class="hljs-number">10</span>,<span class="hljs-number">2</span>)
cbrt(<span class="hljs-number">12</span>) <span class="hljs-comment">// for cube root</span>
exp(<span class="hljs-number">10</span>)
</code></pre>
<h3 id="heading-function-definition"><strong>Function definition</strong></h3>
<pre><code class="lang-scala"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span></span>(a:<span class="hljs-type">Int</span>, b:<span class="hljs-type">Int</span>):<span class="hljs-type">Int</span> = a + b
<span class="hljs-keyword">val</span> sum:<span class="hljs-type">Int</span> = add(<span class="hljs-number">2</span>, <span class="hljs-number">10</span>) <span class="hljs-comment">//val specifies immutability of Int sum</span>
println(<span class="hljs-string">"The value of the sum is: "</span> + sum)
</code></pre>
<p>As you have noticed, pretty much anything that appears after <code>:</code> specifies the type. Also, there is no explicit <code>return</code> statement. The value of the last expression is always returned automatically. Check the next piece of code:</p>
<pre><code class="lang-scala"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">MyFunc</span></span>(a:<span class="hljs-type">Int</span>):<span class="hljs-type">Int</span> = {
    a + <span class="hljs-number">1</span>
    a + <span class="hljs-number">2</span>
    a + <span class="hljs-number">3</span>
}
<span class="hljs-keyword">val</span> p = <span class="hljs-type">MyFunc</span>(<span class="hljs-number">10</span>) <span class="hljs-comment">// Here I deliberately dropped the type of val p, and Scala does not complain about it.</span>
println(<span class="hljs-string">"The value of p is: "</span> + p)
</code></pre>
<h3 id="heading-conditionals-in-scala"><strong>Conditionals in Scala</strong></h3>
<p>Now let us jump into Scala’s If...Else Expression Blocks and Loops.</p>
<h2 id="heading-type-level-programming-in-scala-coming-soon"><strong>Type-level programming in Scala (coming soon)</strong></h2>
<h2 id="heading-fundamentals-of-scala"><strong>Fundamentals of Scala</strong></h2>
<p>In this section, I would like to cover the unique part of Scala, the side that stands apart from the crowd.</p>
<h3 id="heading-in-types-we-trust"><strong>In types we trust!</strong></h3>
<p>In Scala, you can trust your code more than the codes developed in other languages. You want a coding platform where in there if your code compiles, then you should be fine to go. In Scala you know if your types are wrong at compile time not at runtime.</p>
<h3 id="heading-functions-are-first-class-citizens-in-scala"><strong>Functions are first-class citizens in Scala</strong></h3>
<p>One of the concepts in Scala that looks very new to Java users is that in Scala <em>functions</em> are <em>types</em>. In Scala, just like the recent developments in Java 8, you can pass functions around. Not something that we were used to. In your function, you can be very specific about what type of input you expect the function to accept and what should be the return type.</p>
<p>So in Scala function types are based on a) The <em>number</em> and the <em>type</em> of input parameters and b) The return type. So in the MyFunc function that we have defined above (<a target="_blank" href="http://behsys.com/mohsen/Scala-Tutorial-Scala-by-Example.html#function-definition">here</a>), the function takes an Int and returns a type Int. As another example, we may have a function that takes two Int as input and returns a string:</p>
<pre><code class="lang-scala"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">makeString</span></span>(x: <span class="hljs-type">Int</span>, y: <span class="hljs-type">Int</span>): <span class="hljs-type">String</span> = x + <span class="hljs-string">" and "</span> + y
</code></pre>
<p>I could have defined the above function like this:</p>
<pre><code class="lang-scala"><span class="hljs-keyword">val</span> makeString: (<span class="hljs-type">Int</span>, <span class="hljs-type">Int</span>) =&gt; <span class="hljs-type">String</span> = (x, y) =&gt; x + <span class="hljs-string">" and "</span> + y
</code></pre>
<p>The above code says that I'm going to define a function named <code>MakeString</code> that takes two integers and generates and returns a String. Those two incoming parameters are Integers <code>x</code> and <code>y</code> and the return String is x + " and " + y. Now I can try the above code on REPL:</p>
<pre><code class="lang-scala">scala&gt; makeString(<span class="hljs-number">2</span>,<span class="hljs-number">4</span>)
res1: <span class="hljs-type">String</span> = <span class="hljs-number">2</span> and <span class="hljs-number">4</span>
</code></pre>
<p>Note that in Scala the last executable statement of a function is what it will return.</p>
<h3 id="heading-recursion-and-stack-overflow"><strong>Recursion and Stack Overflow</strong></h3>
<p><code>For-each</code> loops as well as <code>while loops</code>, <code>do loops</code>, etc are all iterations. Java is designed to accommodate iterations, and it's not very well at handling recursions. In contrast, Scala, being a functional language, avoids iterations and more gears toward recursion.</p>
<p>Let us write a function that computes the sum of the first natural <code>n</code> natural numbers:</p>
<pre><code class="lang-scala"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sumn</span></span>(n: <span class="hljs-type">Int</span>): <span class="hljs-type">Int</span> = {
    <span class="hljs-keyword">if</span> (n == <span class="hljs-number">0</span>) <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> n + sumn(n<span class="hljs-number">-1</span>)
}
println(<span class="hljs-string">"The sum of first 10 natural numbers is: "</span> + sumn(<span class="hljs-number">10</span>))
</code></pre>
<p>By increasing <code>n</code>, we will reach a point where we will get a stack overflow error. Let us see how Scala overcomes the limitations of the call stack. Let's rewrite the above code, this time using the concept of <code>Tail Calls</code> to avoid the stack overflow message:</p>
<pre><code class="lang-scala"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sumn</span></span>(n: <span class="hljs-type">Int</span>, acc: <span class="hljs-type">Int</span>): <span class="hljs-type">Int</span> = {
    <span class="hljs-keyword">if</span> (n == <span class="hljs-number">0</span>) acc <span class="hljs-keyword">else</span> sumn(n<span class="hljs-number">-1</span>, acc + n)
}
println(<span class="hljs-string">"The sum of first 10 natural numbers is: "</span> + sumn(<span class="hljs-number">10</span>, <span class="hljs-number">0</span>))
</code></pre>
<p>If you need more clarifications on this then please visit <a target="_blank" href="https://web.archive.org/web/20200219220522/https://oldfashionedsoftware.com/2008/09/27/tail-recursion-basics-in-scala/">here.</a></p>
<h3 id="heading-hhttpswebarchiveorgweb20200219220522httpsoldfashionedsoftwarecom20080927tail-recursion-basics-in-scalaigher-order-function-in-scala"><a target="_blank" href="https://web.archive.org/web/20200219220522/https://oldfashionedsoftware.com/2008/09/27/tail-recursion-basics-in-scala/"><strong>H</strong></a><strong>igher order function in Scala</strong></h3>
<p>A function is eligible to be ca<a target="_blank" href="https://web.archive.org/web/20200219220522/https://oldfashionedsoftware.com/2008/09/27/tail-recursion-basics-in-scala/">lled</a> a higher order if <em>It can be passed a function OR</em> It returns a function</p>
<pre><code class="lang-scala"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sqrt</span></span>(x: <span class="hljs-type">Int</span>)= x * x

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sum</span></span>(f: <span class="hljs-type">Int</span> =&gt; <span class="hljs-type">Int</span>, a: <span class="hljs-type">Int</span>, b: <span class="hljs-type">Int</span>): <span class="hljs-type">Int</span> = {
    <span class="hljs-keyword">if</span> (a == b) f(b) <span class="hljs-keyword">else</span> f(a) + sum(f, a + <span class="hljs-number">1</span>, b)
}

println(<span class="hljs-string">"The sum of square of number sbetween 10 and 20 is: "</span> + sum(sqrt, <span class="hljs-number">10</span>, <span class="hljs-number">20</span>))
</code></pre>
<p>In the above example, the function <code>sum</code> is called a higher-order function.</p>
<h3 id="heading-anonymous-functions-in-scala"><strong>Anonymous functions in Scala</strong></h3>
<p>Let's say that we need to compute the sum of the square of numbers between two integers, <em>a</em> and <em>b</em>.</p>
<pre><code class="lang-scala"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">sum</span></span>(f: <span class="hljs-type">Int</span> =&gt; <span class="hljs-type">Int</span>, a: <span class="hljs-type">Int</span>, b: <span class="hljs-type">Int</span>): <span class="hljs-type">Int</span> = {
    <span class="hljs-keyword">if</span> (a == b) f(b) <span class="hljs-keyword">else</span> f(a) + sum(f, a + <span class="hljs-number">1</span>, b)
}
println(<span class="hljs-string">"Here the assumpotion is that a is always smaller than b. I'm not cheking if that assumption is indeed true or not!"</span>)
println(<span class="hljs-string">"The sum of squares netween 10 and 20 is: "</span> + sum(x =&gt; x*x, <span class="hljs-number">10</span>, <span class="hljs-number">20</span>))
</code></pre>
<p>In this example <code>x =&gt; x*x</code> is an <em>anonymous function</em> that takes <em>x</em> as an input and returns <em>x^2</em>.</p>
<p>Note: Can you explain why the code does not compile properly if I replace <em>x\</em>x<em> with </em>scala.math.pow(x,2)*?</p>
<h3 id="heading-map-filter-and-reduce-the-methods-of-collections"><strong>Map, Filter, and Reduce: The methods of collections</strong></h3>
<p>Let's build an array of type Int that covers all of the integers from 100 to 500. The task is to:</p>
<ul>
<li><p>Compute the square root of each element of the array</p>
</li>
<li><p>Filter the ones that are bigger than 450.</p>
</li>
<li><p>Compute the sum of all the elements of the vector.</p>
</li>
</ul>
<p>Now let's see the Map, Filter, and Reduce in action.</p>
<pre><code class="lang-scala"><span class="hljs-keyword">import</span> <span class="hljs-type">Array</span>._
<span class="hljs-keyword">var</span> <span class="hljs-type">A0</span> = range(<span class="hljs-number">100</span>, <span class="hljs-number">500</span>)
<span class="hljs-keyword">val</span> <span class="hljs-type">A1</span> = <span class="hljs-type">A0</span>.map(x =&gt; x*x)
<span class="hljs-keyword">val</span> <span class="hljs-type">A2</span> = <span class="hljs-type">A0</span>.filter(x =&gt; x &gt; <span class="hljs-number">450</span>)
<span class="hljs-keyword">val</span> <span class="hljs-type">A3</span> = <span class="hljs-type">A0</span>.reduce((x, y) =&gt; x + y)
</code></pre>
<p>The above code is self-explanatory. Let's add another example, this time with <code>Vectors</code>. Vectors are built for accessing its elements in constant time. Their elements can be modified easily, a feature that makes them easier to use. The comments in the code explain the process:</p>
<pre><code class="lang-scala"><span class="hljs-comment">// Lets begin by making an empty Vector.</span>
<span class="hljs-keyword">val</span> v = scala.collection.immutable.<span class="hljs-type">Vector</span>.empty
<span class="hljs-comment">// Now we will make three Vectors, v1, v2, and v3</span>
<span class="hljs-keyword">val</span> v1 =  v :+ <span class="hljs-number">1</span> :+ <span class="hljs-number">2</span> :+<span class="hljs-number">3</span>
<span class="hljs-keyword">val</span> v2 = <span class="hljs-type">Vector</span>(<span class="hljs-number">2</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>);
<span class="hljs-keyword">val</span> v3 =  <span class="hljs-type">Vector</span>(<span class="hljs-number">3</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>)
<span class="hljs-comment">// The idea here is to compute the sum of v1, v2 and v3</span>
<span class="hljs-keyword">val</span> sum = <span class="hljs-type">Vector</span>(v1, v2, v2).transpose.map(_.sum)
</code></pre>
<h3 id="heading-pattern-matching-in-scala"><strong>Pattern matching in Scala</strong></h3>
<p>If you tag a <code>.r</code> to any string, scala will make that string into a regular expression.</p>
<h2 id="heading-define-a-class-in-scala"><strong>Define a class in Scala</strong></h2>
<p>Ok, now we have everything in place to get more real and implement our first scala class. The idea here is borrowed from the world of the <em>Internet of Things (IoT)</em>, the buzzword that we hear a lot these days.</p>
<p>Let's imagine that an LED is connected to the internet. We would like to check its status, and we want to be able to turn it on and off. Also, we want to know the time since the last change in its status. To implement the idea let's create the Time class.</p>
<pre><code class="lang-scala"><span class="hljs-keyword">import</span> java.util.<span class="hljs-type">Calendar</span>

<span class="hljs-keyword">case</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Time</span>(<span class="hljs-params">val hour: <span class="hljs-type">Int</span>, val minute: <span class="hljs-type">Int</span></span>) </span>{
    <span class="hljs-keyword">val</span> inMinutes:<span class="hljs-type">Int</span> = hour * <span class="hljs-number">60</span> + minute
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">-</span></span>(that: <span class="hljs-type">Time</span>): <span class="hljs-type">Int</span> = <span class="hljs-keyword">this</span>.inMinutes - that.inMinutes
}
</code></pre>
<p>Perfect. So now we can get the difference between two time stamps. Now it is time to create the class <code>LED</code>. This class needs to be able to store the time stamp it's created. Also, we will need to implement methods for changing its status only when the object(the LED) is not at the desired status.</p>
<pre><code class="lang-scala"><span class="hljs-keyword">case</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LED</span>(<span class="hljs-params"></span>) </span>{

    <span class="hljs-keyword">var</span> now = <span class="hljs-type">Calendar</span>.getInstance()
    <span class="hljs-keyword">var</span> hour = now.get(<span class="hljs-type">Calendar</span>.<span class="hljs-type">HOUR</span>)
    <span class="hljs-keyword">var</span> minute = now.get(<span class="hljs-type">Calendar</span>.<span class="hljs-type">MINUTE</span>)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> time = <span class="hljs-keyword">new</span> <span class="hljs-type">Time</span>(hour, minute)
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">var</span> internalStatus = <span class="hljs-number">0</span>

    <span class="hljs-keyword">override</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">toString</span> </span>= <span class="hljs-string">s"The LED has a status of <span class="hljs-subst">$internalStatus</span>. The status has not changed since <span class="hljs-subst">${statusTime()}</span> minute(s) ago."</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">report</span> </span>{ println(<span class="hljs-keyword">this</span>) }  <span class="hljs-comment">// uses toString</span>

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">statusTime</span></span>() = {
        now = <span class="hljs-type">Calendar</span>.getInstance()
        <span class="hljs-keyword">var</span> cHour = now.get(<span class="hljs-type">Calendar</span>.<span class="hljs-type">HOUR</span>)
        <span class="hljs-keyword">var</span> cMinute = now.get(<span class="hljs-type">Calendar</span>.<span class="hljs-type">MINUTE</span>)
        <span class="hljs-type">Time</span>(cHour, cMinute) - <span class="hljs-keyword">this</span>.time
    }

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">turnOn</span></span>() = {
        <span class="hljs-keyword">if</span> (internalStatus == <span class="hljs-number">0</span>) {
            now = <span class="hljs-type">Calendar</span>.getInstance()
            hour = now.get(<span class="hljs-type">Calendar</span>.<span class="hljs-type">HOUR</span>)
            minute = now.get(<span class="hljs-type">Calendar</span>.<span class="hljs-type">MINUTE</span>)
            internalStatus = <span class="hljs-number">1</span>
            time = <span class="hljs-type">Time</span>(hour, minute)
            println(<span class="hljs-string">"The status has changes to ON"</span>)
        } <span class="hljs-keyword">else</span> {
            println(<span class="hljs-string">"The LED is already ON. No change in the status!"</span>)
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">turnOff</span></span>() = {
        <span class="hljs-keyword">if</span> (internalStatus == <span class="hljs-number">1</span>) {
            now = <span class="hljs-type">Calendar</span>.getInstance()
            hour = now.get(<span class="hljs-type">Calendar</span>.<span class="hljs-type">HOUR</span>)
            minute = now.get(<span class="hljs-type">Calendar</span>.<span class="hljs-type">MINUTE</span>)
            internalStatus = <span class="hljs-number">0</span>
            time = <span class="hljs-type">Time</span>(hour, minute)
            println(<span class="hljs-string">"The status has changes to OFF"</span>)
        } <span class="hljs-keyword">else</span> {
            println(<span class="hljs-string">"The LED is already OFF. No change in the status!"</span>)
        }
    }
}
</code></pre>
<p>Now let's make an instance of the class <code>LED</code> and see its behavior in REPL:</p>
<pre><code class="lang-scala">scala&gt; <span class="hljs-keyword">var</span> myLED = <span class="hljs-keyword">new</span> <span class="hljs-type">LED</span> <span class="hljs-comment">//Here I new a class. We are not passing any value to it. Although a nice extention of the class LED could be to add the posibility of specifing the state of LED when creating it.</span>
myLED: <span class="hljs-type">LED</span> = <span class="hljs-type">LED</span>()

scala&gt; myLED.time
res1: <span class="hljs-type">Time</span> = <span class="hljs-type">Time</span>(<span class="hljs-number">10</span>,<span class="hljs-number">33</span>)

scala&gt; myLED.status
res2: <span class="hljs-type">Int</span> = <span class="hljs-number">0</span>

scala&gt; myLED statusTime
res84: <span class="hljs-type">Int</span> = <span class="hljs-number">2</span>
</code></pre>
<h3 id="heading-extend-a-class-in-scala-subclassing"><strong>Extend a class in Scala: Subclassing</strong></h3>
<p>This section has to be completed, but if you are interested you may want to take a look <a target="_blank" href="http://www.scala-lang.org/old/node/125">here</a>.</p>
<h3 id="heading-extending-an-object-in-scala"><strong>Extending an object in Scala</strong></h3>
<p>This section has to be completed, but if you are interested you may want to take a look <a target="_blank" href="http://stackoverflow.com/questions/7625040/is-there-any-way-to-extend-an-object">here</a>.</p>
<h2 id="heading-conclusions"><strong>Conclusions</strong></h2>
<p>In Scala, there is a special keyword called <code>case</code>.</p>
<p>In the follow-up post, we will go through concise OO and powerful functional collections in Scala.</p>
<p>Have a look at <a target="_blank" href="http://www.artima.com/pins1ed/stateful-objects.html">here</a> for more examples.!!</p>
<hr />
<h2 id="heading-reference"><strong>Reference</strong></h2>
<ul>
<li><p><a target="_blank" href="https://class.coursera.org/progfun-002/class/index">Functional Programming Principles in Scala</a></p>
</li>
<li><p><a target="_blank" href="https://gist.github.com/GMadorell/7554384">some code</a></p>
</li>
<li><p><a target="_blank" href="http://www.artima.com/pins1ed/functional-objects.html">functional-objects</a></p>
</li>
</ul>
<hr />
<blockquote>
<p>It’s easy to lie with statistics. It’s hard to tell the truth without statistics.</p>
<p>Andrejs Dunkels</p>
</blockquote>
<p>*Cover Image Credit: DALL·E 3</p>
]]></content:encoded></item><item><title><![CDATA[A Data Scientist's Chronicle of Lessons Learned and Strategies for Success]]></title><description><![CDATA[Adapted from the source: Read the full article here.

"A data scientist combines hacking, statistics, and machine learning to collect, scrub, examine, model, and understand data. Data scientists are not only skilled at working with data, but they als...]]></description><link>https://thegradient.io/a-data-scientists-chronicle-of-lessons-learned-and-strategies-for-success</link><guid isPermaLink="true">https://thegradient.io/a-data-scientists-chronicle-of-lessons-learned-and-strategies-for-success</guid><category><![CDATA[Data Science]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[lessons]]></category><dc:creator><![CDATA[Mohsen Davarynejad]]></dc:creator><pubDate>Mon, 05 Feb 2024 23:00:00 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1707901372397/16104666-2e1d-4be9-8249-3f413104b1d5.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Adapted from the source: <a target="_blank" href="https://dataqubed.io/blog/a-data-scientists-chronicle-of-lessons-learned-and-strategies-for-success/">Read the full article here</a>.</p>
<blockquote>
<p>"A data scientist combines hacking, statistics, and machine learning to collect, scrub, examine, model, and understand data. Data scientists are not only skilled at working with data, but they also value data as a premium product."</p>
<p>— Erwin Caniba</p>
</blockquote>
<p>Around 9 years ago, I decided to leave academia in the pursuit of putting my learnings to the test. On that occasion, I have decided to pen down my experiences gathered over the last 9 years of my professional voyage; a journey that has taken me through diverse industries, from the corridors of academia to the landscapes of corporate challenges. I distill my experiences into a set of principles, strategies, and wisdom gained through years of exploration.</p>
<ul>
<li><p>Always <strong>challenge your stakeholders</strong> on the problem definitions, problem assumptions, and the importance of the problem at hand. Make sure to understand the business context and challenges of your stakeholders.</p>
</li>
<li><p>In many real-world and industrial use cases, <strong>leveraging an existing solution</strong> promotes efficiency by avoiding unnecessary repetition. Often, you will find that your particular problem has already been solved. If it initially appears to be unique, attempt to <strong>abstract the problem</strong>, and then look for an algorithm that suits this view. This method usually uncovers that your issue corresponds to well-known problems that have established solutions.</p>
</li>
<li><p><strong>Start from design</strong>, before code. Your initial design is the key to the project's success. Break down the solution into testable maintainable pieces. Review your design, put it out there, and ask relevant people to challenge it. Feedback is a gift, so embrace it.</p>
</li>
<li><p>Start with implementing <strong>Unit tests</strong>.</p>
</li>
<li><p>Be <strong>visible</strong>, don’t work in a silo, and always speak your mind.</p>
</li>
<li><p><strong>Focus on the data</strong> rather than focusing on the model. Also, think about other sources of data that can be used. Check on their availability and accessibility.</p>
</li>
</ul>
<blockquote>
<p>"Data science isn't about the quantity of data but rather the quality."</p>
<p>— Joo Ann Lee</p>
</blockquote>
<ul>
<li><p>Always start from the <strong>simplest model</strong> possible, which ticks the requirements.</p>
</li>
<li><p>More often than not the <strong>models make strong assumptions</strong>. So it's always critical to accompany your analysis and findings with a sensitivity analysis: How robust are your conclusions to the model assumptions? Reliable inferences can be only in light of model-specific sensitivity analysis.</p>
</li>
<li><p>Ensure that the open-source tools embedded in decision-support solutions are accompanied by thorough documentation and will continue to <strong>receive support</strong> over time. Additionally, a strong user community around these tools is essential for securing the necessary expertise for future needs.</p>
</li>
<li><p><strong>Solution adoption</strong> is more important than model performance. Use interpretable and glass box models whenever possible.</p>
</li>
<li><p>You cannot improve what you cannot measure. So always have your <strong>KPIs</strong> in place, and study the impact of the changes on the KPI.</p>
</li>
<li><p>It's good to work hard and get the whole to-do list finished. But more importantly, you need to focus on the <strong>impact</strong>. Protrize the work, measure the impact of each feature, gauge, and show flexibility.</p>
</li>
<li><p>When joining a new organization ensure a <strong>code review</strong> process is in place. Make it part of the organization if it's not already. Always look for ways to make the code review process smoother and more productive.</p>
</li>
<li><p><strong>Praising good work</strong> is more than a formality; it is a celebration of the commitment to excellence. Each milestone achieved and every challenge overcome is a testament to the unwavering dedication of individuals who go above and beyond. So recognize them in the meeting/stand-ups.</p>
</li>
<li><p><strong>Naming is important.</strong> When implementing the solution, you will need to cook names along the way, whether it's process names, file names, variable names, function names, etc. Consider this as a selling opportunity.</p>
</li>
<li><p>Share your results with your stakeholders in <strong>incremental steps</strong>. And focus on the story and the implications of the results of your work. In most cases, your stakeholders have no interest in the details of the used algorithms and failed solutions. Just get to the bottom line and avoid technical presentations.</p>
</li>
<li><p>Do not focus only on building a great ML model in a notebook. <strong>Think automation</strong>. Automate as much as possible.</p>
</li>
<li><p>When it comes to maintaining legacy code, start with Increased test coverage, API solidifying, and small steps toward an ideal state isolated to subsystems behind the solidified interfaces. <strong>No Massive refactors</strong> as they introduce too much change to reason about at once, and any mistake costs momentum and trust, which can lead to rolling back and abandonment at great expense. Make sure to take small steps that are easy to roll back. Avoid all-or-nothing ethos around the success of the refactor.</p>
</li>
<li><p>Do not stop learning. <strong>Self-development</strong> is the key to both individual and team success.</p>
</li>
</ul>
<blockquote>
<p><em>"The best way to learn data science is to do data science."</em></p>
<p>— <em>Chanin Nantasenamat</em></p>
</blockquote>
<hr />
<p>* <sup> Image Credit: DALL-E 3 with the prompt: Create an image where a puzzle game is featured at the center. As you move towards the outer edges of the image, the puzzle pieces seamlessly transform into pins. These pins are intricately connected to each other with wires, resembling a complex network of junctions in a bustling city. Ensure that the pins exhibit a variety of colors to enhance the vibrant and dynamic feel of the cityscape</sup></p>
]]></content:encoded></item><item><title><![CDATA[Classification with imbalanced data]]></title><description><![CDATA[Consider the problem of predicting late passengers at the airport. Based on some statistics, only around 8% of passengers are considered late. Assuming the availability of good features like Age, Gender, Nationality, Country of residence, Walking dis...]]></description><link>https://thegradient.io/classification-with-imbalanced-data</link><guid isPermaLink="true">https://thegradient.io/classification-with-imbalanced-data</guid><category><![CDATA[Imbalanced]]></category><category><![CDATA[classification]]></category><dc:creator><![CDATA[Mohsen Davarynejad]]></dc:creator><pubDate>Mon, 29 Jan 2024 08:17:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706300910719/71284001-70b2-4856-a4a4-a681c49d6b5b.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Consider the problem of predicting late passengers at the airport. Based on some statistics, only around 8% of passengers are considered late. Assuming the availability of good features like <em>Age</em>, <em>Gender</em>, <em>Nationality</em>, <em>Country of residence</em>, <em>Walking distance from the baggage drop-off point to the gate,</em> etc., the easy solution would be to build a random forest and train it using let’s say 80% of the available data set. The other 20% of data is reserved for testing. What does it mean If the classifier gets an accuracy of 92%? Bad.</p>
<p>So the question that comes to mind is why does it happen, and how to handle imbalanced classification problems?</p>
<p>The answer to the first question, why does it happen, is a simple one. When the problem at hand is imbalanced, the ML algorithm has little information about the minority class. So it’s not a simple task to come up with a list of features that are informative to discriminate the classes.</p>
<p>For the second question, how to handle the problem, one may provide several answers, mainly supported by conceptual reasoning and simulated results. We shall review a number of them in this article. Without loss of generality, binary classification is considered here.</p>
<h1 id="heading-approaches-to-deal-with-imbalanced-data-sets">Approaches to deal with imbalanced data sets</h1>
<p>The skewed class distribution is quantized by the imbalance ratio (IR) and is defined as the <em>ratio of the number of instances in the majority class</em> to <em>the number of examples in the minority class.</em></p>
<p>The approaches are categorized into two groups: the <em>internal approaches</em> and <em>external approaches</em>. While the former group aims at creating new algorithms or modifying the existing ones, the latter acts on the data by resampling to diminish the effect caused by class imbalance.</p>
<h2 id="heading-internal-approaches">Internal approaches</h2>
<p>Internal approaches modify the existing algorithms or create new ones equipped with approaches to handle imbalanced classification problems. They may adapt the decision threshold to create a bias toward the minority class. Or may modify the cost function to compensate the minority class.</p>
<h2 id="heading-external-approaches">External approaches</h2>
<p>This group acts on the data rather than the learning method. Their advantage over internal approaches is their independence from the classifier used. One of the methods to deal with imbalance classification problems is the <em>Data Sampling</em> Method, each with its characteristics, strengths, and weaknesses. These techniques assume that a fully balanced dataset can be attained. <em>Data Sampling</em> methods transform the imbalanced data set into balanced data by under-sampling the majority class, over-sampling the minority class, and/or generating synthesized data to bring the class ratio to 50:50. A very well-known representative of the latter method is known as <em>Synthetic Minority Oversampling Technique</em> or <em>SMOTE</em>. Although several studies have shown little to no difference between these data sampling techniques, we shall review all three of them.</p>
<h3 id="heading-random-undersampling-rus">Random Undersampling (RUS)</h3>
<p>Random Undersampling (RUS) tries to balance the two classes by reducing the size of the majority class accomplished by removing instances of the majority instance. Observations from the majority class are selected and removed from the database at random, and the process continues until the desired class ratio is reached.</p>
<h3 id="heading-random-oversampling-ros">Random Oversampling (ROS)</h3>
<p>As you might have already guessed, Random Oversampling balances the dataset by increasing the size of the minority class. The desired class ratio is achieved by duplicating samples from the minority class. The items to be duplicated are selected at random.</p>
<p>ROS, when compared to RUS, ensures efficient use of information and prevents information loss. On the other hand, the chance of overfitting is high when using random oversampling, meaning that the training accuracy may be improved at the cost of lower performance on the test set.</p>
<h3 id="heading-synthetic-data-generation">Synthetic Data Generation</h3>
<p>This group of techniques is a type of oversampling with the aim of balancing the classes by generating synthetic data. The most widely used and well-known member of this group is the <em>synthetic minority oversampling technique</em> (SMOTE). This set of algorithms oversamples the minority class by the use of k-nearest neighbors.</p>
<h2 id="heading-cost-sensitive-learning-csl">Cost-sensitive Learning (CSL)</h2>
<p>Cost-sensitive learning framework takes advantage of both External approaches (by adding costs to instances) and Internal approaches (by modifying the internal learning process to accept costs). In this framework, the cost of misclassification of the minority class is higher in comparison to the cost of misclassification of the majority class. The cost matrix is composed of four quadrants, that resemble the confusion matrix. The penalty for True Positive and True Negatives is zero, thus the total cost is the weights sum of \(C_{FN}\) and \(C_{FP}\) and may be computed using the following equation:</p>
<p>$$C_T=C_{FN}∗||FN||+C_{FP}∗||FP||$$</p><p>where \(||FN||\) is the number of false negatives (positive examples wrongly predicted) and \(||FP||\) is the number of False negatives (negative observations wrongly predicted). Depending on the application, \(C_{FN} &gt; C_{FP} \) or \(C_{FP} &gt; C_{FN}\).</p>
<h1 id="heading-selection-of-performance-metrics">Selection of performance metrics</h1>
<h2 id="heading-roc-curve-and-how-to-plot-it">ROC curve and how to plot it?</h2>
<p>In most cases, the output of the classifier is a score (and not the probability) bounded in the range of 0 and 1. If the output is less than a threshold \(\theta\) then we would say the instance belongs to class \(-1\), otherwise, it belongs to class \(1\). Note that \(\theta\) is bounded between the max and min value of the output of the model, which might be 0 and 1.</p>
<p>For every \(\theta\), the true positive ratio (TPR) and false positive ratio (FPR) can be computed. TPR is the ratio of correct positive results to all positive samples available during the test. FPR is a number of incorrect positive results to all negative samples available during the test.</p>
<p>Now every choice for \(\theta\) corresponds to a point in the ROC Space. In ROC Space the X-axis specifies the False Positive Rate (also known as Specificity) and the Y-axis represents the True Positive Rate (also known as Sensitivity). So the y-axis reflects the proportion of actual positives that are correctly classified as positives.</p>
<p>The area under the ROC curve is known as the AUC (area under curve) or <em>c-statistic</em>. In the ML community AUC statistic is the most often used metric for model comparison.</p>
<p>Note that the area between the ROC curve and the no-discrimination line (the diagonal line) is known as the <em>Gini Coefficient</em>.</p>
<p>ROC curves are known to be insensitive to class balance, hence a good choice for imbalanced datasets.</p>
<h1 id="heading-further-reading">Further Reading</h1>
<p>There is a wealth of literature on classifiers in imbalanced domains, along with a comprehensive exploration of the challenges they pose. For readers interested in delving deeper into the topic, below is a list of challenges and references that address them.</p>
<ul>
<li><p>Noisy data and imbalanced domains [Knowledge discovery from imbalanced and noisy data, 2009].</p>
</li>
<li><p>Dataset shift: A very well-known concept in ML space that refers to variations in the distribution of data between the training and test datasets [The balancing trick: Optimized sampling of imbalanced datasets—A brief survey of the recent State of the Art, 2020] and [Rethinking the Value of Labels for Improving Class-Imbalanced Learning, 2020]</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706299698228/91d0cc56-1038-456e-a66f-9190072b2065.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-summary">Summary</h1>
<p>While Imbalanced classification is a common issue in many ML and data science, there is no single-bullet solution to address the challenge. Strategies such as resampling and the use of various evaluation metrics have the potential to address the challenges. What remains important is continuously monitoring the models we have in production and being cautious of potential data drifts.</p>
<hr />
<blockquote>
<p>Behind every great product there is a great product manager. That is why there are so few great products out there.</p>
<p>A cool data scientist, Delft</p>
</blockquote>
<p><sub>Cover Image Credit: Chris Wren and Kenn Brown/mondoworks.</sub></p>
]]></content:encoded></item><item><title><![CDATA[11 must-know Python Pandas tips and tricks for data scientists]]></title><description><![CDATA[Adapted from the original source: Read the full article here.
Pandas is considered the most widely used tool for data manipulation, filtering, and wrangling. It comes with enormous features and functionalities designed for fast and easy data analytic...]]></description><link>https://thegradient.io/11-must-know-python-pandas-tips-and-tricks-for-data-scientists</link><guid isPermaLink="true">https://thegradient.io/11-must-know-python-pandas-tips-and-tricks-for-data-scientists</guid><category><![CDATA[Python]]></category><category><![CDATA[python beginner]]></category><dc:creator><![CDATA[Mohsen Davarynejad]]></dc:creator><pubDate>Fri, 26 Jan 2024 05:48:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706247702039/60116bce-1793-4935-96c1-83b9333abd28.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Adapted from the original source: <a target="_blank" href="https://dataqubed.io/blog/pandas-tips-and-tricks-for-data-scientists/">Read the full article here</a>.</p>
<p>Pandas is considered the most widely used tool for data manipulation, filtering, and wrangling. It comes with enormous features and functionalities designed for fast and easy data analytics. As a data scientist, I use its features on a daily basis, and in this post, I’d love to share with you some of the tricks of pandas.</p>
<p>I hope that this crafted list of features serves as a quick reference and gives you a good starting point for learning Pandas. The listed features come in no specific order, so no conclusions can be made on the order.</p>
<p>I will be using the NVDA ticker price data set for this post. So before going into the feature lists, I’ll share with you a few lines of code to download the data locally.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706247367147/77d9c9e5-3598-4c6e-8361-889f3740408d.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-pull-the-nvda-exchange-pricing-data">Pull the NVDA exchange pricing data</h3>
<p>We will be using Yahoo! Finance's API to download some market data. For that, we will be using the yfinance Python package. Follow <a target="_blank" href="https://pypi.org/project/yfinance/">this link and install yfinance</a>. I installed it using the following single line of code:</p>
<pre><code class="lang-python">!pip install yfinance
</code></pre>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> pickle
<span class="hljs-keyword">import</span> yfinance <span class="hljs-keyword">as</span> yf
</code></pre>
<p>Let's first pull the historical NVDA exchange rate from the Yahoo! Finance's API.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_yf_data</span>(<span class="hljs-params">ticker, period = <span class="hljs-string">"1mo"</span></span>):</span>
    <span class="hljs-string">'''Pull and cache yfinance data into a dataframe. Caching is important for avoiding rate limits.'''</span>
    pkl_file_name = ticker.replace(<span class="hljs-string">" "</span>, <span class="hljs-string">"_"</span>) + <span class="hljs-string">"_"</span> + period 
    cache_path = <span class="hljs-string">'{}.pkl'</span>.format(pkl_file_name).replace(<span class="hljs-string">'/'</span>,<span class="hljs-string">'-'</span>)
    <span class="hljs-keyword">try</span>:
        <span class="hljs-comment"># Check if the pickle file is in the working directory.</span>
        f = open(cache_path, <span class="hljs-string">'rb'</span>)
        ticker_df = pickle.load(f)   
        print(<span class="hljs-string">'Loaded {} from cache'</span>.format(ticker))
    <span class="hljs-keyword">except</span> (OSError, IOError) <span class="hljs-keyword">as</span> e:
        <span class="hljs-comment"># The data is not locally avaiable. Download it and store it in a form of pickle file. </span>
        print(<span class="hljs-string">'Downloading {} from yfinance'</span>.format(ticker))
        ticker_df = yf.download(ticker, period=period)
        ticker_df.to_pickle(cache_path)
        print(<span class="hljs-string">'Cached {} at {}'</span>.format(ticker, cache_path))
    <span class="hljs-keyword">return</span> ticker_df

<span class="hljs-comment"># Pull NVDA and AAPL price from exchange data</span>
NVDA_price= get_yf_data(<span class="hljs-string">"NVDA"</span>, period=<span class="hljs-string">"10d"</span>)

<span class="hljs-comment"># If you would like to download more tickers you try the following:</span>
NVDA_price= get_yf_data(<span class="hljs-string">"NVDA APP TSLA"</span>, period=<span class="hljs-string">"1mo"</span>)
<span class="hljs-comment"># The above will download the Nvidia, Apple and Tesla share prices. </span>

NVDA_price.tail()
</code></pre>
<p>Now that we have the data ready at hand, let's have a look at my selection of Pandas tips and tricks.</p>
<h3 id="heading-number-11-apply-aggregations-on-dataframe-and-series">Number 11: Apply aggregations on DataFrame and Series</h3>
<pre><code class="lang-python">NVDA_price.agg([<span class="hljs-string">'mean'</span>, <span class="hljs-string">'min'</span>, <span class="hljs-string">'max'</span>])

NVDA_price.High.agg([<span class="hljs-string">'mean'</span>, <span class="hljs-string">'min'</span>, <span class="hljs-string">'max'</span>])
</code></pre>
<p><code>.describe()</code> provides the same functionality but <code>.agg()</code> is more flexible as far as I can tell.</p>
<pre><code class="lang-python">NVDA_price.describe()
</code></pre>
<h3 id="heading-number-10-all-you-need-is-pandasprofiling">Number 10: All you need is pandas_profiling</h3>
<p><code>pandas_profiling</code> is a Python library mainly used for initial data exploration. A running example:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Make sure that you have the pandas_profiling installed.</span>
<span class="hljs-comment"># To install pandas_profiling run: !pip install pandas_profiling</span>

<span class="hljs-keyword">import</span> pandas_profiling

NVDA_price.shape
<span class="hljs-comment"># Chart the NVDA pricing data</span>
pandas_profiling.ProfileReport(NVDA_price)
</code></pre>
<p>This helps you with a few lines of code and time-saving tricks when exploring the data. The <code>pandas_profiling</code> library comes with more features than the one listed above. Interested readers are referred to the official website.</p>
<p>The package provides an extensive exploratory data analysis (EDA) that includes reporting on different types of correlations, such as Pearson's r and Phik coefficient (φk). Phik (φk) is a new correlation coefficient that works consistently between categorical, ordinal, and interval variables. Phik can capture non-linear dependency and revert to the Pearson correlation coefficient in the case of the bivariate normal input distribution. Read more <a target="_blank" href="https://phik.readthedocs.io/en/latest/index.html">here</a>.</p>
<h3 id="heading-number-9-easy-way-to-convert-data-toint-type"><strong>Number 9: Easy way to convert data to</strong><code>int</code> type</h3>
<p>This is a simple but useful trick! When converting the data into <code>int</code> type, the most common approach is to use <code>.astype('int')</code>. However, if there are strings or other invalid types, you will face an error, and the conversion will fail. An alternative is to use the <a target="_blank" href="http://pd.to"><code>pd.to</code></a><code>_numeric()</code> command which will handle the errors. You may try this for yourself.</p>
<h3 id="heading-number-8-break-up-strings-in-multiple-columns">Number 8: Break up strings in multiple columns</h3>
<p>A simple trick for splitting a column into multiple columns using a split function:</p>
<pre><code class="lang-python">NVDA_price[<span class="hljs-string">'column_name'</span>] = NVDA_price[<span class="hljs-string">'column_name'</span>].str.split(<span class="hljs-string">" "</span>, expand=<span class="hljs-literal">True</span>)
</code></pre>
<h3 id="heading-number-7-str">Number 7: .str</h3>
<p>I’d like to show you how awesome <code>.str</code> is with <code>Pandas Series</code>. Check the following piece of code:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Covert the Data column to str.</span>
NVDA_price[<span class="hljs-string">'Date_str'</span>] = NVDA_price.index.astype(str)
<span class="hljs-comment"># And take the first 4 elements of the resulting string. </span>
NVDA_price[<span class="hljs-string">'Year_str'</span>] = NVDA_price[<span class="hljs-string">'Date_str'</span>].str[:<span class="hljs-number">4</span>]
</code></pre>
<p>It's awesome how they make this bit of magic work.</p>
<h3 id="heading-number-6-concatenate-strings">Number 6: Concatenate strings</h3>
<p>It’s so easy with the pandas to create a new column by combining two existing columns:</p>
<pre><code class="lang-python">NVDA_price[<span class="hljs-string">'ts'</span>] = NVDA_price.index.values.astype(np.int64) // <span class="hljs-number">10</span> ** <span class="hljs-number">9</span> 
NVDA_price[<span class="hljs-string">'price_ts'</span>] = NVDA_price[<span class="hljs-string">"Open"</span>].map(str) + <span class="hljs-string">" - "</span> + NVDA_price[<span class="hljs-string">"ts"</span>].map(str)
NVDA_price[<span class="hljs-string">'price_ts'</span>].head()
</code></pre>
<p>and to get them back again:</p>
<pre><code class="lang-python">NVDA_price[<span class="hljs-string">'price'</span>], NVDA_price[<span class="hljs-string">'ts'</span>] = zip(*NVDA_price.price_ts.str.split(<span class="hljs-string">' - '</span>, <span class="hljs-number">1</span>))
NVDA_price[[<span class="hljs-string">'price_ts'</span>, <span class="hljs-string">'price'</span>, <span class="hljs-string">'ts'</span>]].head()
</code></pre>
<h3 id="heading-number-5-percentage-of-missing-data">Number 5: Percentage of missing data</h3>
<p>To get the percentage of missing data in columns and print them in descending order:</p>
<pre><code class="lang-python"><span class="hljs-comment"># gives % of missing data in columns!</span>
(NVDA_price.isnull().sum()/NVDA_price.isnull().count()).sort_values(ascending=<span class="hljs-literal">False</span>)
</code></pre>
<h3 id="heading-number-4-highly-correlated-columns">Number 4: Highly correlated columns</h3>
<p>Let’s assume that we want to build a predictive model and we would like to know which columns are highly correlated (bigger than 0.10) to the column <code>Volume</code>!</p>
<pre><code class="lang-python">corr_coeff = NVDA_price.corr()[<span class="hljs-string">'Volume'</span>].abs().sort_values()
corr_coeff[corr_coeff &gt; <span class="hljs-number">0.10</span>]
</code></pre>
<h3 id="heading-number-3-apply-and-lambda-functions">Number 3: Apply and lambda functions</h3>
<p>One of the most awesome things that you can do with pandas is that you can store objects such as <code>networkx</code> graphs in them. Then you can easily <code>.apply()</code> the metrics and algorithms on each graph and see the tabulated results in a nice pandas dataframe. You can also easily <code>.apply()</code> custom functions or <code>lambdas</code> to modify all objects at once. The index then can be used to keep track of everything and to keep results near their original objects.</p>
<p>In the example let’s assume that you have multiple networks from different years. We will make a graph at <code>random</code>.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> networkx <span class="hljs-keyword">as</span> nx
<span class="hljs-keyword">import</span> itertools
<span class="hljs-keyword">import</span> random

years, graphs = list(zip(*[(year, nx.barbell_graph(random.randint(<span class="hljs-number">2</span>,<span class="hljs-number">10</span>),random.randint(<span class="hljs-number">2</span>,<span class="hljs-number">50</span>))) <span class="hljs-keyword">for</span> year <span class="hljs-keyword">in</span> range(<span class="hljs-number">2010</span>,<span class="hljs-number">2019</span>)]))
df = pd.DataFrame({<span class="hljs-string">"graph"</span>: graphs}, index=years)

df[<span class="hljs-string">"number_of_nodes"</span>] = df.graph.apply(nx.number_of_nodes)
df[<span class="hljs-string">"number_of_edges"</span>] = df.graph.apply(nx.number_of_edges)
df[<span class="hljs-string">"transitivity"</span>] = df.graph.apply(nx.transitivity)
</code></pre>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">nodes_odd_degree</span>(<span class="hljs-params">g</span>):</span>
    <span class="hljs-comment"># Calculate list of nodes with odd degree</span>
    nodes_odd_degree = [v <span class="hljs-keyword">for</span> v, d <span class="hljs-keyword">in</span> g.degree() <span class="hljs-keyword">if</span> d % <span class="hljs-number">2</span> == <span class="hljs-number">1</span>]
    <span class="hljs-keyword">return</span> nodes_odd_degree

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">len_odd_node_pairs</span>(<span class="hljs-params">g</span>):</span>
    <span class="hljs-comment"># Compute all pairs of odd nodes and return the length of list of tuples!</span>
    odd_node_pairs = list(itertools.combinations(nodes_odd_degree(g), <span class="hljs-number">2</span>))
    <span class="hljs-keyword">return</span> len(odd_node_pairs)
</code></pre>
<pre><code class="lang-python">df[<span class="hljs-string">"nodes_odd_degree"</span>] = df.graph.apply(nodes_odd_degree)
df[<span class="hljs-string">"len_nodes_odd_degree"</span>] = df[<span class="hljs-string">"nodes_odd_degree"</span>].apply(len)
df[<span class="hljs-string">"len_odd_node_pairs"</span>] = df.graph.apply(len_odd_node_pairs)

<span class="hljs-comment"># And now print a selection of columns:</span>
df[[<span class="hljs-string">"number_of_nodes"</span>, <span class="hljs-string">"number_of_edges"</span>, <span class="hljs-string">"transitivity"</span>, <span class="hljs-string">"nodes_odd_degree"</span>, <span class="hljs-string">"len_nodes_odd_degree"</span>, <span class="hljs-string">"len_odd_node_pairs"</span>]]
</code></pre>
<h3 id="heading-number-2-dropduplicates-vs-unique">Number 2: drop_duplicates vs unique</h3>
<p>Let’s assume that you have a column with millions of entries and you need to find the unique set of values It. <code>df.column_name.drop_duplicates(keep="first", inplace=False)</code> is a lot faster than <code>df.column_name.unique()</code>. Can be tested using <code>%timeit</code>.</p>
<p>The <code>keep="first"</code> option drops all the duplicates except for the first occurrence.</p>
<h3 id="heading-number-1-ufuncs">Number 1: Ufuncs</h3>
<p>As explained <a target="_blank" href="https://towardsdatascience.com/pandas-tips-and-tricks-33bcc8a40bb9">here</a> Pandas <code>Ufuncs</code> is much better than <code>.apply</code> command.</p>
<h2 id="heading-wrap-up">Wrap-Up</h2>
<p>This post should give you an idea of some Pandas tricks commonly used by data scientists. The list aims to make your code more efficient.</p>
<p>In my next post, I'll share some basic concepts you need for working with data in <code>PySpark</code>. The post will cover topics such as reading and writing data from CSV files, along with some basic statistical analysis and visualization of data.</p>
<hr />
<h3 id="heading-notes">Notes:</h3>
<p>1 - The official panda<a target="_blank" href="https://learnpython.com/course/python-data-science?icn=blogTraffic&amp;ici=link-ArticleBottom">s cheat sheet can be downloaded from he</a><a target="_blank" href="https://github.com/pandas-dev/pandas/blob/master/doc/cheatsheet/Pandas_Cheat_Sheet.pdf">re</a>.</p>
<p>2- Link to the <a target="_blank" href="https://github.com/mdavarynejad">notebook of this tutorial</a>.</p>
<h3 id="heading-refernces">Refernces:</h3>
<p>1 - <a target="_blank" href="https://www.youtube.com/watch?v=FxrGx8cPJlQ&amp;t=33s">Data School</a></p>
<p>2 - <a target="_blank" href="https://gist.github.com/luerhard/703716567879afefa59c06e5af48c371">Lukas Erhard</a></p>
<hr />
<p>Please leave a message below if you would like to share your thoughts or if you like to share your tricks on Pandas.</p>
]]></content:encoded></item><item><title><![CDATA[Explainable boosting machine]]></title><description><![CDATA[Adapted from the original source: Read the full article here.
The business impact of machine learning models is becoming increasingly significant whether it is in marketing campaign budget allocation or credit risk management. However, the lack of in...]]></description><link>https://thegradient.io/explainable-boosting-machine</link><guid isPermaLink="true">https://thegradient.io/explainable-boosting-machine</guid><category><![CDATA[EBM]]></category><category><![CDATA[Glass Box]]></category><category><![CDATA[xai]]></category><dc:creator><![CDATA[Mohsen Davarynejad]]></dc:creator><pubDate>Tue, 23 Jan 2024 12:39:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1706013256579/0016f59e-7b70-49d1-8dd3-e8ddf4e6d206.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Adapted from the original source: <a target="_blank" href="https://dataqubed.io/blog/explainable-boosting-machine/">Read the full article here.</a></p>
<p>The business impact of machine learning models is becoming increasingly significant whether it is in marketing campaign budget allocation or credit risk management. However, the lack of interpretability and explainability of many machine learning models makes them not only difficult to <em>trust</em> but also difficult to <em>debug</em>. When the end user can comprehend the decision-making process of a machine learning model, they are more likely to accept, trust, and adopt the model's outputs, giving rise to reliable model-based decisions.</p>
<p>The easiest way to ensure interpretability is to use interpretable models. Consequently, there is a growing interest in the development and utilization of interpretable machine learning models.</p>
<p>Explainable Boosting Machine (EBM) originally developed at Microsoft Research is an inherently interpretable machine learning model that gained increasing popularity in a variety of business applications due to its predictive performance and low computational cost. It falls into a category of ML models known as "Glass box". Not only it can capture non-linear relationships between dependent and independent variables, but it also has a built-in mechanism to capture interactions among independent variables. at its heart, it uses some of the well-known ML techniques like bagging and gradient boosting.</p>
<p>Explainable Boosting Machine is a special case of ensemble models, which involve training multiple very simple decision trees and combining their predictions to obtain a final prediction.</p>
<p>Imagine we are given a dataset with <em>n</em> features. The first decision tree is trained only on the first feature. The residuals are then calculated and we continue by training another model but this time only using the second feature. The process continues until the last model is trained in a boosting fashion using the last feature. The order of the features will not impact the results since we ensure to keep the learning rate very small. Now we have the <em>first iteration</em> completed. We continue the process for many many iterations, let's say 10,000 iterations. At the end of the cycle, we have 10,000 small trees trained on feature 1 that can be summarized as a graph. We can extract a graph for all the features. These series of graphs with size <em>n</em> construct our model.</p>
<p>The ability to model complex relationships and interactions while maintaining explainability makes the Explainable Boosting Machine a powerful tool for a wide range of predictive modeling tasks.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1706132145393/4cba68db-738a-4dcf-b904-d9fb53c9d29a.gif" alt="thegradient.io EBM Boosting machine " class="image--center mx-auto" /></p>
<h3 id="heading-conclusion">Conclusion:</h3>
<p>You probably heard about the trade-off between explainability and accuracy of machine learning models. The more accurate the model is, the more complex it is and less explainable. EBMs violate this trade-off. With EBMs you will get high accuracy while getting a highly explainable model with an added bonus of editability. This makes EBMs the perfect candidate of choice for many real-world applications that support model-based decisions.</p>
<h3 id="heading-inherently-interpretable-ml-models">Inherently interpretable ML models</h3>
<p>Interested in this topic? Read more on "How to design inherently interpretable machine learning models" by Sudjianto and Zhang (2021)</p>
<hr />
<p>In my next post, I should follow up on the fairness, weakness detection, reliability, robustness, and resilience of XAI.</p>
]]></content:encoded></item><item><title><![CDATA[Overfitting in ML models]]></title><description><![CDATA[Overfitting happens when a model is more complex than it should be and starts to fit the noise in the data (or some degree of that) instead of the underlying pattern. Overfitting leads to poor model performance on new and unseen data.
While there is ...]]></description><link>https://thegradient.io/overfitting-in-ml-models</link><guid isPermaLink="true">https://thegradient.io/overfitting-in-ml-models</guid><category><![CDATA[PiML]]></category><category><![CDATA[Overfitting]]></category><category><![CDATA[Model Validation]]></category><category><![CDATA[Explainability]]></category><dc:creator><![CDATA[Mohsen Davarynejad]]></dc:creator><pubDate>Sun, 21 Jan 2024 13:52:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705867904726/6256e5fa-3462-4f09-9b12-c20bd58ede41.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Overfitting happens when a model is more complex than it should be and starts to fit the noise in the data (or some degree of that) instead of the underlying pattern. Overfitting leads to poor model performance on new and unseen data.</p>
<p>While there is no single answer for what level of overfitting is acceptable (although we know it partially depends on the specific application, goals, and tradeoffs), a common approach is to use a validation data set to monitor the model’s performance during training. When the performance of the model on the validation set starts to degrade while its performance on the training set continues to improve (typically presented as a U-shaped curve) we are transitioning between under- and overfitting regimes. At this point, you can stop training the model or use techniques like regularization or data augmentation to prevent overfitting. While overfitting leads to poor generalization (beyond the training set) and reduces the predictive power of the model, almost always, some level of overfitting is expected and acceptable.</p>
<h3 id="heading-avoiding-overfitting">Avoiding overfitting</h3>
<p>Few techniques are known to mitigate overfitting.</p>
<ul>
<li><p><strong>Regularization:</strong> A very well-known technique that helps prevent overfitting by adding a penalty term to the model's cost function. Regularization discourages overly complex or extreme parameter values. Subsampling rows/columns in XGBoost or ML models with similar architectures is another form of regularization.</p>
</li>
<li><p><strong>Model Simplification:</strong> Use a simple model but not simpler. A simple model has fewer parameters and less possibility to fit noise. Also ensure to discard less discriminatory features and only keep the most relevant ones.</p>
</li>
<li><p><strong>Knowledge Distillation:</strong> Train a smaller, more regularized model to mimic the behavior of a larger, more complex model. This helps in efficient knowledge transfer from the complex model to the simpler one.</p>
</li>
<li><p><strong>Cross-Validation:</strong> While its primary purpose is not to prevent overfitting, it provides valuable insights into how well a model is likely to perform on unseen data and can indirectly help in preventing overfitting.</p>
</li>
<li><p><strong>Early Stopping:</strong> Stop model training once its performance on validation set plateaus or starts to worsen.</p>
</li>
<li><p><strong>Data Augmentation:</strong> This includes not only collecting more diverse and representative data but also Introducing random noise into the input data (to make the model more robust and prevent it from relying too much on specific patterns in the data).</p>
</li>
</ul>
<p>As a rule of thumb, I would not be comfortable deploying an ML model whose performance drops from train to test by more than 2-3%. If that is the case ensure to use any of the techniques listed above to alleviate the situation.</p>
<h3 id="heading-benign-overfitting">Benign overfitting</h3>
<p>A very related phenomenon in machine learning is what is known as "benign overfitting", where a model is overfitting the training data but still performs well on the test data. These models have great expressive power. While the performance of these models might be very good concerning testing data, these models might be very sensitive to small perturbations in the inputs; thus, very fragile in production.</p>
<p>Benign overfitting can be the consequence of Abundance of Data or Robust Model Architecture to name a few. While benign overfitting suggests that the model can handle the noise with no significant degradation in its ability to make accurate predictions on new, unseen data, we need to ensure models generalize well without relying on spurious patterns in the data.</p>
<p>While overfitting does not necessarily harm generalization, it negatively impacts model sensitivity and robustness.</p>
<p>In case you need to get a bit more practical in selecting the right model with reasonable performance and robustness you need to look into PiML (<a target="_blank" href="https://github.com/SelfExplainML/PiML-Toolbox">PiML GitHub</a>).</p>
<pre><code class="lang-bash">pip install PiML
</code></pre>
<h3 id="heading-piml-for-identifying-model-weaknesses-before-putting-them-into-production">PiML for Identifying model weaknesses before putting them into production</h3>
<p>Well-tuned models tend to be more robust in production when compared to overtly fit and underfit models. That holds true even when we have an overfit/underfit model with similar performance on the test data as a well-tuned model. So once you've gotten to a reasonable threshold of model performance, you're better off focusing on model stability, model generalizability, and the policies you'll put in place around the model than on over-optimizing the model itself. It's the combination of the model + the decision strategies around it that will yield meaningful results in lending. So Identify model weaknesses before putting them into production.</p>
<p>Let's have a quick look into the impact of benign overfitting on model robustness using PiML.</p>
<h3 id="heading-the-interplay-between-model-robustness-and-the-quality-of-fit">The interplay between model robustness and the quality of fit</h3>
<p>A robust model can effectively manage variations, noise, or outliers in the input data without experiencing a substantial drop in performance. Experimental studies show that the performance of a well-tuned model is statistically significantly less affected by perturbations in input data when compared to that of overfit models.</p>
<p>Interested to read more on this topic? Continue here.</p>
<hr />
<h3 id="heading-avoid-overfitting-in-dnns"><strong>Avoid overfitting in DNNs</strong></h3>
<p>In part 2 of the same series, I'll cover techniques used to avoid overfitting in DNNs.</p>
<hr />
<p>What's next? Markov Chain Monte Carlo for approximation of the posterior distribution: Metropolis-Hastings vs Hamiltonian Monte Carlo (Read <a target="_blank" href="https://arxiv.org/pdf/2006.16194.pdf">here</a>)</p>
]]></content:encoded></item><item><title><![CDATA[PyTorch for image classification - Part 1]]></title><description><![CDATA[1. Introduction
This tutorial shows how to classify images using a pretraining Residual Neural Network (ResNet). Image classification is a supervised learning problem with the objective of training a model that learns the relationship between input f...]]></description><link>https://thegradient.io/pytorch-for-image-classification-part-1</link><guid isPermaLink="true">https://thegradient.io/pytorch-for-image-classification-part-1</guid><category><![CDATA[pytorch tutorials]]></category><category><![CDATA[pytorch]]></category><category><![CDATA[image classification]]></category><category><![CDATA[resnet]]></category><category><![CDATA[Python]]></category><category><![CDATA[Model Evaluation]]></category><dc:creator><![CDATA[Mohsen Davarynejad]]></dc:creator><pubDate>Tue, 16 Jan 2024 16:35:37 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705868010722/edc36388-02b0-47aa-b744-8ba7b0a85dcf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-1-introduction">1. Introduction</h2>
<p>This tutorial shows how to classify images using a pretraining Residual Neural Network (ResNet). Image classification is a supervised learning problem with the objective of training a model that learns the relationship between input features and corresponding labels. The output of a classification model is a discrete label or category, indicating the class to which the input belongs.</p>
<p>We will demonstrate the following concepts:</p>
<ul>
<li><p>Efficiently loading a dataset off the disk.</p>
</li>
<li><p>Pulling a pre-trainer model and fine-tuning it.</p>
</li>
<li><p>Mitigate overfitting by data augmentation and dropout.</p>
</li>
</ul>
<p>And we will follow a standard machine-learning workflow:</p>
<ul>
<li><p>Examine and understand the data</p>
</li>
<li><p>Build an input pipeline</p>
</li>
<li><p>Build the model</p>
</li>
<li><p>Train the model</p>
</li>
<li><p>Test the model</p>
</li>
<li><p>Improve the model and repeat the process</p>
</li>
</ul>
<p>In addition, we will also demonstrate how to save models locally.</p>
<h3 id="heading-steps">Steps</h3>
<ul>
<li><p>Creating a custom dataset</p>
</li>
<li><p>Build a DNN model in PyTorch</p>
</li>
<li><p>Training the MLP model classifier in PyTorch</p>
</li>
<li><p>Plotting of loss and accuracy curve on training a test data</p>
</li>
<li><p>Evaluation of model performance - Confusion matrix</p>
</li>
</ul>
<h2 id="heading-2-setup">2- Setup</h2>
<p>Import TensorFlow and other necessary libraries:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd 
<span class="hljs-keyword">import</span> random

<span class="hljs-keyword">from</span> sklearn.metrics <span class="hljs-keyword">import</span> confusion_matrix
<span class="hljs-keyword">from</span> sklearn.preprocessing <span class="hljs-keyword">import</span> LabelEncoder
<span class="hljs-keyword">from</span> tqdm <span class="hljs-keyword">import</span> tqdm_notebook <span class="hljs-keyword">as</span> tqdm

<span class="hljs-keyword">import</span> os
<span class="hljs-keyword">import</span> time
<span class="hljs-keyword">from</span> copy <span class="hljs-keyword">import</span> deepcopy
<span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> Image
<span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> ImageOps
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-keyword">import</span> torchvision.transforms <span class="hljs-keyword">as</span> transforms
<span class="hljs-keyword">from</span> torchvision.models <span class="hljs-keyword">import</span> resnet50, resnet101
<span class="hljs-keyword">import</span> torch
<span class="hljs-keyword">from</span> torch.utils.data <span class="hljs-keyword">import</span> Dataset, DataLoader
<span class="hljs-keyword">from</span> torch.utils.data.sampler <span class="hljs-keyword">import</span> SubsetRandomSampler
<span class="hljs-keyword">import</span> torch.nn.functional <span class="hljs-keyword">as</span> F

<span class="hljs-keyword">from</span> torchsummary <span class="hljs-keyword">import</span> summary

<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sn

<span class="hljs-keyword">from</span> utils <span class="hljs-keyword">import</span> flatten_list, read_files_in_path
</code></pre>
<p>It's important to specify where the tensors and models are stored and processed, whether on a CPU or a GPU. The following code will ensure to work on the default GPU if available.</p>
<pre><code class="lang-python">device = torch.device(<span class="hljs-string">"cuda"</span>) <span class="hljs-keyword">if</span> torch.cuda.is_available() <span class="hljs-keyword">else</span> torch.device(<span class="hljs-string">"cpu"</span>)
print(<span class="hljs-string">f'Using <span class="hljs-subst">{device}</span> for inference'</span>)
</code></pre>
<h2 id="heading-3-train-and-test-data">3- Train and Test data</h2>
<p>The dataset is divided into training and validation sets, offering a diverse collection of images of your choice. We assume that the training set, residing at <code>BASE_PATH_TRAIN</code>, serves as the foundation for our model to learn and generalize. Meanwhile, the validation set at <code>BASE_PATH_VALID</code> provides a litmus test for the model's accuracy and effectiveness.</p>
<pre><code class="lang-python">BASE_PATH_TRAIN = <span class="hljs-string">"Images/Train"</span>
BASE_PATH_VALID = <span class="hljs-string">"Images/Valid"</span>
</code></pre>
<p>Let's look into the dataset and extract the number of classes within our training set. I need to exclude the generic "Others" category.</p>
<pre><code class="lang-python">classes = os.listdir(BASE_PATH_TRAIN)
classes = [x <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> classes <span class="hljs-keyword">if</span> <span class="hljs-string">"Others"</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> x]
print(<span class="hljs-string">f'Number of classes: <span class="hljs-subst">{len(classes)}</span>: <span class="hljs-subst">{classes}</span>'</span>)
</code></pre>
<p>Next, we will index the full path of images and their corresponding category and also introduce an element of randomness by shuffling the rows. Shuffling ensures that our model encounters a diverse mix of images during each epoch of training, enhancing its ability to generalize and recognize patterns effectively.</p>
<pre><code class="lang-python">training_data = read_files_in_path(path = BASE_PATH_TRAIN)
training_data = training_data.sample(frac=<span class="hljs-number">1</span>).reset_index(drop=<span class="hljs-literal">True</span>)
print(training_data.shape)
training_data.head()

validation_data = read_files_in_path(path = BASE_PATH_VALID)
print(validation_data.shape)
validation_data.head()
</code></pre>
<h2 id="heading-4-decoding-the-dataset-label-encoding"><strong>4- Decoding the Dataset: Label Encoding</strong></h2>
<p>Next, we introduce an important step — label encoding. This process not only facilitates the training of the model but also streamlines the interpretation of results.</p>
<pre><code class="lang-python">lb = LabelEncoder()
training_data[<span class="hljs-string">'encoded_labels'</span>] = lb.fit_transform(training_data[<span class="hljs-string">'labels'</span>])
validation_data[<span class="hljs-string">'encoded_labels'</span>] = lb.transform(validation_data[<span class="hljs-string">'labels'</span>])

<span class="hljs-comment"># Construct the Mapping Dictionary</span>
mapping = dict(zip(lb.classes_, lb.transform(lb.classes_)))
reversed_mapping = {value: key <span class="hljs-keyword">for</span> key, value <span class="hljs-keyword">in</span> mapping.items()}
</code></pre>
<p>The above code not only encodes the categorical labels but also constructs a dictionary that maps classes to their corresponding encoded values.</p>
<h2 id="heading-5-crafting-a-data-pipeline-and-built-in-data-transformation"><strong>5- Crafting a Data Pipeline and built-in data tran</strong>s<strong>formation</strong></h2>
<p>For this project, we prefer to write our very own data loader from scratch mainly because it will give us full control over the transformations we like to apply to the images. The pipeline loads the images off disk, applies the specified transformations, and makes the images ready for the model.</p>
<pre><code class="lang-python"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreatePipeline</span>(<span class="hljs-params">Dataset</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span>(<span class="hljs-params">self, data, transform</span>):</span>
        super(CreatePipeline, self).__init__()
        self.data = data.values
        self.transform = transform

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__len__</span>(<span class="hljs-params">self</span>):</span>
        <span class="hljs-keyword">return</span> len(self.data)

    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__getitem__</span>(<span class="hljs-params">self, x</span>):</span>
        image, _, label = self.data[x]
        im = np.asarray(Image.open(image).convert(<span class="hljs-string">'RGB'</span>))
        <span class="hljs-keyword">if</span> self.transform <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> <span class="hljs-literal">None</span>:
            im = self.transform(im)

        <span class="hljs-keyword">return</span> im, label

train_pipeline = CreatePipeline(training_data, image_transforms[<span class="hljs-string">'train'</span>])
train_loader = DataLoader(train_pipeline, batch_size=BATCH_SIZE)

validation_pipeline = CreatePipeline(validation_data, image_transforms[<span class="hljs-string">'valid'</span>])
validation_loader = DataLoader(validation_pipeline, batch_size=BATCH_SIZE)
</code></pre>
<p>where <code>image_tranforms</code> defines a dictionary of image transformations for both training and validation datasets. All images pass through the transformation phase (random rotations and flips, color jittering, etc) to ensure the ResNet model is exposed to a rich and varied dataset. These random transformations ensure a more robust model and prevent overfitting. This also helps to expose the model to more aspects of the data and generalize better.</p>
<p>The list of transformations is below:</p>
<pre><code class="lang-python">image_transforms = {<span class="hljs-string">'train'</span>:   transforms.Compose([transforms.ToPILImage(),
                               transforms.ToTensor(),
                               transforms.RandomRotation(degrees=<span class="hljs-number">5</span>),
                               transforms.Resize((SIZE, SIZE)),
                               transforms.RandomResizedCrop(<span class="hljs-number">224</span>, scale=(<span class="hljs-number">0.9</span>, <span class="hljs-number">1.0</span>)),
                               transforms.RandomHorizontalFlip(),                                                 
                               transforms.ColorJitter(brightness=<span class="hljs-number">.1</span>, hue=<span class="hljs-number">.1</span>),
                               transforms.Normalize(mean=(<span class="hljs-number">0.485</span>, <span class="hljs-number">0.456</span>, <span class="hljs-number">0.406</span>), std=(<span class="hljs-number">0.229</span>, <span class="hljs-number">0.224</span>, <span class="hljs-number">0.225</span>))]),

                    <span class="hljs-string">'valid'</span>:   transforms.Compose([transforms.ToPILImage(),
                               transforms.ToTensor(),
                               transforms.RandomHorizontalFlip(),
                               transforms.ColorJitter(brightness=<span class="hljs-number">.1</span>, hue=<span class="hljs-number">.1</span>),
                               transforms.Resize((SIZE, SIZE)),
                               transforms.Normalize(mean=(<span class="hljs-number">0.485</span>, <span class="hljs-number">0.456</span>, <span class="hljs-number">0.406</span>), std=(<span class="hljs-number">0.229</span>, <span class="hljs-number">0.224</span>, <span class="hljs-number">0.225</span>))])
                   }
</code></pre>
<p>Applying distinct transformations to training and validation datasets ensures a balance between data augmentation (which helps the model generalize better during training) and ensuring a fair evaluation of the model's performance on unseen data during validation.</p>
<h2 id="heading-6-model-selection">6- Model Selection</h2>
<p>In the realm of deep learning, the choice of neural network architecture is a critical decision that can significantly impact the model's performance. ResNet, short for Residual Network, stands out as a powerful and influential architecture due to its ability to address challenges associated with training very deep networks.</p>
<p>Here's why ResNet is a compelling choice for our use case, image classification:</p>
<ol>
<li><p><strong>The Vanishing Gradient Problem:</strong> One common challenge in training deep neural networks is the vanishing gradient problem, where the gradients diminish as they backpropagate through numerous layers. This can hinder the training of deep networks. ResNet introduces skip connections or residual connections (shortcut paths), allowing information to bypass certain layers. This architecture mitigates the vanishing gradient problem and makes it possible to train extremely deep networks. The skip connections also allow the model to learn identity mappings, making it easier to optimize and converge during training.</p>
</li>
<li><p><strong>Performance on Image Classification:</strong> ResNet architectures have demonstrated remarkable performance on image classification tasks, particularly in competitions like ImageNet. The ability to capture intricate features and patterns in images contributes to their success.</p>
</li>
<li><p><strong>Transfer Learning Capability:</strong> Pre-trained ResNet models on large datasets (e.g., ImageNet) can be used as a starting point for a variety of computer vision tasks. Leveraging transfer learning allows models to benefit from features learned on diverse datasets.</p>
</li>
<li><p><strong>Adaptability to Different Scales:</strong> The skip connections in ResNet allow the model to adapt to features at different scales, capturing both low-level and high-level information in images.</p>
</li>
<li><p><strong>Consistent State-of-the-Art Performance:</strong> ResNet variants have consistently achieved state-of-the-art performance in various computer vision tasks, making them a reliable choice for image classification.</p>
</li>
</ol>
<h2 id="heading-7-model-hyperparameters">7- Model Hyperparameters</h2>
<p>With our training and validation Dataset was meticulously prepared</p>
<pre><code class="lang-python"><span class="hljs-comment"># Hyperparameters for Training</span>
BATCH_SIZE = <span class="hljs-number">16</span>
EPOCHS = <span class="hljs-number">24</span>
LR = <span class="hljs-number">0.1</span>

SIZE = <span class="hljs-number">224</span>
NUM_CLASSES = len(lb.classes_)
print(<span class="hljs-string">f"NUM_CLASSES: <span class="hljs-subst">{NUM_CLASSES}</span>"</span>)

RANDOM_SEED = <span class="hljs-number">42</span>

MODEL_STORE_NAME = <span class="hljs-string">'equipment_classification.pt'</span>
</code></pre>
<p>The above hyperparameters set the batch size to 16 images, allowing the model to incrementally learn from diverse samples. We set the Epochs equal to 24, with each epoch representing a complete pass through the entire training dataset. The Learning Rate (LR) of 0.1 determines the size of the steps our model takes. Each image is resized to a dimension of 224x224 pixels (SIZE) and the number of classes NUM_CLASSES is set. The RANDOM_SEED at 42, ensures the reproducibility of our training process, providing a consistent backdrop for our model's learning journey. We also set the MODEL_STORE_NAME.</p>
<h2 id="heading-part-2-of-this-series-will-be-published-soon">Part 2 of this series will be published soon!!</h2>
<hr />
]]></content:encoded></item><item><title><![CDATA[Navigating the Depths of Data Science and Machine Learning in TheGradient.io]]></title><description><![CDATA[Hello, Data Enthusiasts!
I'm thrilled to welcome you to TheGradient.io, your go-to hub for all things data science, machine learning, and LLM. Whether you're a seasoned data scientist or an aspiring ML engineer, this space is tailored just for you.
W...]]></description><link>https://thegradient.io/navigating-the-depths-of-data-science-and-machine-learning-in-thegradientio</link><guid isPermaLink="true">https://thegradient.io/navigating-the-depths-of-data-science-and-machine-learning-in-thegradientio</guid><category><![CDATA[the gradient]]></category><category><![CDATA[TheGradient.io]]></category><dc:creator><![CDATA[Mohsen Davarynejad]]></dc:creator><pubDate>Sun, 14 Jan 2024 17:21:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1705868541334/d1f030e6-bee9-4277-8e0e-e48cd32904f8.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hello, Data Enthusiasts!</p>
<p>I'm thrilled to welcome you to <a target="_blank" href="http://TheGradient.io">TheGradient.io</a>, your go-to hub for all things data science, machine learning, and LLM. Whether you're a seasoned data scientist or an aspiring ML engineer, this space is tailored just for you.</p>
<p><strong>What's</strong> <a target="_blank" href="http://TheGradient.io"><strong>TheGradient.io</strong></a> <strong>All About?</strong></p>
<p>At <a target="_blank" href="http://TheGradient.io">TheGradient.io</a>, we dive deep into the realms of data science, exploring the latest trends, and practical use cases, and sharing valuable learning materials. Expect a blend of insightful articles, personal experiences, and a curated collection of learning resources that will sharpen your skills in the ever-evolving landscape of data and machine learning.</p>
<p><strong>For Data Scientists and ML Engineers</strong></p>
<p>This space is crafted with you in mind. Expect discussions on cutting-edge techniques, real-world applications, and the occasional coding adventure. Whether you're looking to refine your skills or stay updated on industry trends, <a target="_blank" href="http://TheGradient.io">TheGradient.io</a> is here to be your companion on this exciting journey.</p>
<p><strong>Got Questions? We've Got Answers!</strong></p>
<p>Have a burning question about a machine learning algorithm, data preprocessing, or the best practices in the field? Look no further! This platform is not just about sharing knowledge; it's about building a community. If you've got a question, or a suggestion, or just want to connect with fellow data enthusiasts, don't hesitate to reach out. Your curiosity fuels the discussions here.</p>
<p><strong>Connect with Learning Materials</strong></p>
<p>As we embark on this data-driven adventure together, I'll be sharing learning materials and resources, all neatly organized on my GitHub account. <a target="_blank" href="http://TheGradient.io">TheGradient.io</a> is not just a blog; it's a knowledge hub. Stay tuned for GitHub links accompanying our posts, providing you with hands-on tools and materials to amplify your learning experience.</p>
<p><strong>Get Ready for the Gradient Journey!</strong></p>
<p>Whether you're here to gain insights, share experiences, or connect with a like-minded community, <a target="_blank" href="http://TheGradient.io">TheGradient.io</a> is ready to be your companion in the exciting world of data science and machine learning. Let's dive into the gradient together, where every step brings us closer to mastering the art and science of data.</p>
<p>If you're as passionate about data as I am, welcome aboard! I can't wait to share this journey with you.</p>
<p>Feel free to explore, engage, and enjoy the data-driven ride ahead!</p>
<p>Cheers,</p>
<p>Mohsen Davarynejad</p>
<hr />
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://twitter.com/TheGradient_io/status/1746913124001648817">https://twitter.com/TheGradient_io/status/1746913124001648817</a></div>
]]></content:encoded></item></channel></rss>