{"id":105942,"date":"2026-07-04T11:37:29","date_gmt":"2026-07-04T06:07:29","guid":{"rendered":"https:\/\/staging.nanoschool.in\/wp\/study\/lesson-5-3-3-handling-class-imbalance-in-crop-disease-datasets\/"},"modified":"2026-07-04T11:37:29","modified_gmt":"2026-07-04T06:07:29","slug":"lesson-5-3-3-handling-class-imbalance-in-crop-disease-datasets","status":"publish","type":"tva_lesson","link":"https:\/\/staging.nanoschool.in\/wp\/study\/lesson-5-3-3-handling-class-imbalance-in-crop-disease-datasets\/","title":{"rendered":"Lesson 5.3.3: Handling class imbalance in crop disease datasets"},"content":{"rendered":"<p>Lesson 5.3.3: Handling class imbalance in crop disease datasets  Dashboard \u203a My courses \u203a Course \u203a Lesson 5.3.3: Handling class imbalance in crop disease datasets  <\/p>\n<h2>Lesson 5.3.3: Handling class imbalance in crop disease datasets<\/h2>\n<h1>Lesson 5.3.3: Handling class imbalance in crop disease datasets<\/h1>\n<p>  <span>\u23f2 27 min read<\/span>  <span>\ud83d\udcc4 5414 words<\/span><\/p>\n<p><strong>Learning Objectives<\/strong><\/p>\n<ul>\n<li>Explain why class imbalance can bias machine learning models in crop disease detection.<\/li>\n<li>Identify and compare common techniques for mitigating class imbalance, such as resampling, cost-sensitive learning, and synthetic data generation.<\/li>\n<li>Implement imbalance handling strategies using Python and scikit\u2011learn in a crop disease dataset.<\/li>\n<li>Evaluate the impact of imbalance mitigation on model performance metrics and recognise common pitfalls.<\/li>\n<\/ul>\n<p><strong>Key Terms<\/strong><\/p>\n<table>\n<tbody>\n<tr>\n<th scope=\"row\">Class Imbalance<\/th>\n<td>A situation where the distribution of classes in a dataset is uneven, often leading to biased model predictions towards majority classes.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\">Resampling<\/th>\n<td>Techniques such as oversampling minority classes or undersampling majority classes to balance the dataset.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\">Synthetic Minority Over-sampling Technique (SMOTE)<\/th>\n<td>A method that generates synthetic examples of minority classes by interpolating between existing samples.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\">Cost\u2011Sensitive Learning<\/th>\n<td>Adjusting the learning algorithm to penalise misclassifications of minority classes more heavily.<\/td>\n<\/tr>\n<tr>\n<th scope=\"row\">Precision\u2011Recall Curve<\/th>\n<td>A performance metric that is more informative than accuracy in the presence of class imbalance.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>flowchart TD    A[Data Collection] &#8211;&gt; B[Imbalance Detected]    B &#8211;&gt; C[Resampling Strategies]    C &#8211;&gt; D[Cost-sensitive Learning]    D &#8211;&gt; E[Model Training]    E &#8211;&gt; F[Evaluation]    F &#8211;&gt; G[Deployment]    C &#8211;&gt; E    D &#8211;&gt; E<\/p>\n<h2>Concept: Why Imbalance Matters in Crop Disease Models<\/h2>\n<p>In supervised learning for crop disease detection, the distribution of disease classes often deviates markedly from an even split. For example, a dataset of leaf images might contain 95\u202f% healthy specimens and only 5\u202f% of a particular fungal infection. This skew in the class distribution\u2014known as <em>class imbalance<\/em>\u2014has a cascade of effects that influence the statistical bias of the model, distort evaluation metrics, and, ultimately, jeopardise the reliability of crop yield forecasts used by agronomists and policy makers.<\/p>\n<h3>1. Model Bias Induced by Imbalance<\/h3>\n<p>When the training data are dominated by a majority class, the learning algorithm tends to minimise error on that class, often at the expense of minority classes. In a typical cross\u2011entropy loss, each misclassification contributes equally to the total loss. If 95\u202f% of the samples belong to the healthy class, the optimiser will prioritise reducing errors on healthy instances simply because they are more plentiful. Consequently, the decision boundary is pulled towards the minority class, leading to a systematic bias that manifests as high <strong>false\u2011negative rates for rare diseases<\/strong>.<\/p>\n<p>Bias is not merely a statistical artefact; it translates into tangible agricultural costs. A model that consistently misclassifies a rust infection as healthy will allow the disease to spread unchecked, potentially reducing crop yield by up to 30\u202f% in affected regions. Conversely, over\u2011sensitivity to the majority class can cause over\u2011diagnosis, leading to unnecessary pesticide application and economic waste.<\/p>\n<h3>2. Evaluation Metrics Skewed by Imbalance<\/h3>\n<p>Accuracy is an intuitive metric, but in highly imbalanced settings it can be misleading. Consider a model that predicts every instance as healthy. With a 95\u202f% healthy prevalence, the accuracy would be 95\u202f%, yet the model offers no practical value. More informative metrics include precision, recall, F1\u2011score, and the area under the receiver operating characteristic curve (AUC\u2011ROC). However, these too can be affected by imbalance:<\/p>\n<ul>\n<li><strong>Precision<\/strong> may appear high if the model rarely predicts the minority class, but this does not guarantee that the minority class is correctly identified.<\/li>\n<li><strong>Recall<\/strong> is especially sensitive to minority class performance; a low recall indicates that many disease instances remain undetected.<\/li>\n<li><strong>AUC\u2011ROC<\/strong> is robust to class imbalance in many cases, but when the minority class is extremely rare, the curve can flatten, giving an overly optimistic view of performance.<\/li>\n<\/ul>\n<p>To illustrate, the following Python snippet computes these metrics for a binary classifier on an imbalanced dataset. The code explicitly demonstrates how the minority class can be overlooked if we rely solely on accuracy.<\/p>\n<p>import numpy as npfrom sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score, roc_auc_score<\/p>\n<h1>True labels: 0 = healthy, 1 = disease<\/h1>\n<p>y_true = np.array([0]<em>95 + [1]<\/em>5)          # 95 healthy, 5 diseased<\/p>\n<h1>Predicted probabilities from a model<\/h1>\n<p>y_pred_prob = np.array([0.05]<em>95 + [0.95]<\/em>5)  # perfect predictions<\/p>\n<h1>Threshold at 0.5 to get class predictions<\/h1>\n<p>y_pred = (y_pred_prob &gt;= 0.5).astype(int)print(&#8220;Accuracy:&#8221;, accuracy_score(y_true, y_pred))print(&#8220;Precision:&#8221;, precision_score(y_true, y_pred))print(&#8220;Recall:&#8221;, recall_score(y_true, y_pred))print(&#8220;F1-Score:&#8221;, f1_score(y_true, y_pred))print(&#8220;AUC-ROC:&#8221;, roc_auc_score(y_true, y_pred_prob))<\/p>\n<p><strong>Line\u2011by\u2011line explanation:<\/strong><\/p>\n<ol>\n<li>Import required libraries from numpy and sklearn.metrics.<\/li>\n<li>Define the true labels: 95 instances of class\u202f0 (healthy) followed by 5 instances of class\u202f1 (disease).<\/li>\n<li>Simulate model outputs: low probability (0.05) for healthy, high probability (0.95) for diseased, representing a perfectly discriminative model.<\/li>\n<li>Convert probabilities to binary predictions using a 0.5 threshold.<\/li>\n<li>Compute and display accuracy, precision, recall, F1\u2011score, and AUC\u2011ROC.<\/li>\n<\/ol>\n<p>Even with perfect discrimination, the class imbalance forces us to interpret each metric carefully. In real\u2011world scenarios, models rarely achieve perfect discrimination; hence the risk of misclassifying minority disease instances is far greater.<\/p>\n<h3>3. Real\u2011World Implications for Crop Yield Forecasting<\/h3>\n<p>Yield forecasting models often integrate disease prevalence estimates as a key input. If disease detection is biased, the forecast will under\u2011estimate the impact of a pathogen, leading to insufficient resource allocation. For instance, a misjudged outbreak of wheat mildew could cause a 15\u202f% yield loss, yet the forecast might predict a 2\u202f% reduction, misleading stakeholders.<\/p>\n<p>Moreover, public policy decisions\u2014such as issuing disease alerts or allocating subsidies\u2014rely on accurate disease prevalence data. An imbalanced model that systematically under\u2011reports a rare but devastating disease could delay intervention measures, exacerbating losses.<\/p>\n<h3>4. Mitigation Strategies and Their Trade\u2011offs<\/h3>\n<p>Below is a concise table summarising common techniques to address class imbalance, along with their pros and cons in the context of crop disease modelling.<\/p>\n<table>\n<thead>\n<tr>\n<th>Technique<\/th>\n<th>How It Works<\/th>\n<th>Benefits<\/th>\n<th>Drawbacks<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Resampling (Oversampling Minority)<\/td>\n<td>Duplicate minority instances or create synthetic samples (SMOTE)<\/td>\n<td>Balances class distribution; simple to implement<\/td>\n<td>Risk of overfitting; synthetic data may not capture real variation<\/td>\n<\/tr>\n<tr>\n<td>Resampling (Undersampling Majority)<\/td>\n<td>Remove majority instances to match minority count<\/td>\n<td>Reduces training time; prevents majority bias<\/td>\n<td>Loss of potentially valuable information; may discard rare healthy patterns<\/td>\n<\/tr>\n<tr>\n<td>Cost\u2011Sensitive Learning<\/td>\n<td>Assign higher misclassification cost to minority class<\/td>\n<td>Maintains full dataset; directly penalises false negatives<\/td>\n<td>Requires careful tuning of cost matrix; may destabilise training<\/td>\n<\/tr>\n<tr>\n<td>Ensemble Methods (Balanced Bagging)<\/td>\n<td>Train multiple models on balanced bootstraps and aggregate<\/td>\n<td>Improves robustness; mitigates variance<\/td>\n<td>Computationally intensive; complex model management<\/td>\n<\/tr>\n<tr>\n<td>Threshold Adjustment<\/td>\n<td>Move classification threshold away from 0.5 to favour minority class<\/td>\n<td>Simple post\u2011processing step; no retraining needed<\/td>\n<td>May increase false positives; requires domain\u2011specific calibration<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Choosing the appropriate strategy depends on the severity of imbalance, the cost of false negatives versus false positives, and the computational resources available. In many agricultural settings, a hybrid approach\u2014combining SMOTE with cost\u2011sensitive loss functions\u2014has proven effective.<\/p>\n<h3>5. Conclusion<\/h3>\n<p>Class imbalance is not a peripheral issue; it sits at the heart of reliable crop disease modelling. It biases the learning process, distorts evaluation metrics, and undermines the credibility of yield forecasts that inform critical agronomic decisions. By recognising the multifaceted effects of imbalance and applying targeted mitigation techniques, practitioners can develop models that are both statistically sound and practically valuable for sustaining crop productivity.<\/p>\n<p># Example: Using Weighted Cross\u2011Entropy Loss in PyTorch to Handle Imbalanceimport torchimport torch.nn as nnimport torch.optim as optim<\/p>\n<h1>Assume binary classification: 0 = healthy, 1 = disease<\/h1>\n<h1>Compute class weights inversely proportional to class frequencies<\/h1>\n<p>class_counts = torch.tensor([950, 50], dtype=torch.float32)  # 950 healthy, 50 diseasedclass_weights = 1.0 \/ class_countsclass_weights = class_weights \/ class_weights.sum()  # normalisecriterion = nn.CrossEntropyLoss(weight=class_weights)optimizer = optim.Adam(model.parameters(), lr=1e-3)<\/p>\n<h1>Dummy training loop<\/h1>\n<p>for inputs, targets in dataloader:    optimizer.zero_grad()    outputs = model(inputs)    loss = criterion(outputs, targets)    loss.backward()    optimizer.step()<\/p>\n<table>\n<thead>\n<tr>\n<th>Approach<\/th>\n<th>Weighting Scheme<\/th>\n<th>Typical Use\u2011case<\/th>\n<th>Pros<\/th>\n<th>Cons<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Class\u2011Balanced Sampling<\/td>\n<td>Oversample minority or undersample majority<\/td>\n<td>When data size permits<\/td>\n<td>Simple, effective<\/td>\n<td>Risk of overfitting or information loss<\/td>\n<\/tr>\n<tr>\n<td>Cost\u2011Sensitive Loss<\/td>\n<td>Weighted loss functions (e.g., focal loss)<\/td>\n<td>When preserving data is critical<\/td>\n<td>Retains all samples<\/td>\n<td>Requires careful tuning<\/td>\n<\/tr>\n<tr>\n<td>Ensemble Balancing<\/td>\n<td>Multiple balanced models aggregated<\/td>\n<td>High\u2011variance problems<\/td>\n<td>Robustness<\/td>\n<td>Computational cost<\/td>\n<\/tr>\n<tr>\n<td>Threshold Tuning<\/td>\n<td>Adjust decision threshold post\u2011training<\/td>\n<td>When model is already trained<\/td>\n<td>No retraining<\/td>\n<td>May inflate false positives<\/td>\n<\/tr>\n<tr>\n<td>Synthetic Data Generation (SMOTE)<\/td>\n<td>Create synthetic minority samples<\/td>\n<td>When minority samples are scarce<\/td>\n<td>Enriches dataset<\/td>\n<td>Synthetic noise may mislead model<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span>Activity: Reflect on Class Imbalance Impact<\/span><\/p>\n<p>Think back to the section on why imbalance matters in crop disease models. Consider how a skewed distribution of disease labels could affect model accuracy, precision, and recall. Write a brief reflection (2-4 sentences) on how you would identify imbalance in a new dataset and what initial steps you might take to mitigate its effects.<\/p>\n<h2>Implementation\/Code: Resampling and SMOTE with scikit\u2011learn<\/h2>\n<p>When working with crop disease data the most common stumbling block is class imbalance. A single outbreak can generate thousands of images of diseased leaves while healthy samples are scarce, or vice versa. If left unchecked, machine\u2011learning models will happily learn to predict the majority class and neglect the minority. Resampling techniques \u2013 both undersampling the majority and oversampling the minority \u2013 provide a straightforward way of re\u2011balancing the training data. The Synthetic Minority Over-sampling Technique (SMOTE) takes this further by generating synthetic examples rather than merely duplicating existing ones, which can reduce overfitting.<\/p>\n<h3>1. Preparing the dataset for resampling<\/h3>\n<p>Assume we have already extracted features from crop leaf images and stored them in a Pandas DataFrame called df. The target variable is named label and contains categorical values such as &#8216;healthy&#8217;, &#8216;rust&#8217;, &#8216;blight&#8217;. Before resampling we must convert the categorical labels into numeric form, split the data into training and testing sets, and standardise the features because SMOTE is sensitive to feature scales.<\/p>\n<p>import pandas as pdfrom sklearn.model_selection import train_test_splitfrom sklearn.preprocessing import StandardScalerfrom sklearn.preprocessing import LabelEncoder<\/p>\n<h1>Load the feature matrix<\/h1>\n<p>df = pd.read_csv(&#8216;crop_features.csv&#8217;)<\/p>\n<h1>Separate features and target<\/h1>\n<p>X = df.drop(columns=[&#8216;label&#8217;])y = df[&#8216;label&#8217;]<\/p>\n<h1>Encode labels as integers<\/h1>\n<p>le = LabelEncoder()y_encoded = le.fit_transform(y)<\/p>\n<h1>Train\u2013test split (80\/20)<\/h1>\n<p>X_train, X_test, y_train, y_test = train_test_split(    X, y_encoded, test_size=0.2, stratify=y_encoded, random_state=42)<\/p>\n<h1>Feature scaling \u2013 SMOTE requires the same scale across features<\/h1>\n<p>scaler = StandardScaler()X_train_scaled = scaler.fit_transform(X_train)X_test_scaled = scaler.transform(X_test)<\/p>\n<p><strong>Explanation of each line:<\/strong><\/p>\n<ol>\n<li>import pandas as pd \u2013 imports the Pandas library for data manipulation.<\/li>\n<li>from sklearn.model_selection import train_test_split \u2013 brings in the function that will split our data.<\/li>\n<li>from sklearn.preprocessing import StandardScaler \u2013 provides a simple way to standardise features.<\/li>\n<li>from sklearn.preprocessing import LabelEncoder \u2013 converts string labels into integer codes.<\/li>\n<li>df = pd.read_csv(&#8216;crop_features.csv&#8217;) \u2013 reads the pre\u2011processed feature file.<\/li>\n<li>X = df.drop(columns=[&#8216;label&#8217;]) \u2013 creates a DataFrame with all columns except the target.<\/li>\n<li>y = df[&#8216;label&#8217;] \u2013 extracts the target column.<\/li>\n<li>le = LabelEncoder() \u2013 initialises the encoder.<\/li>\n<li>y_encoded = le.fit_transform(y) \u2013 fits the encoder to the labels and transforms them into numeric form.<\/li>\n<li>train_test_split(&#8230;, stratify=y_encoded, &#8230;) \u2013 splits the data while preserving the class proportions in both sets.<\/li>\n<li>scaler = StandardScaler() \u2013 creates a scaler object.<\/li>\n<li>X_train_scaled = scaler.fit_transform(X_train) \u2013 learns the mean and variance from the training set and applies the transformation.<\/li>\n<li>X_test_scaled = scaler.transform(X_test) \u2013 applies the same transformation to the test set to keep the scaling consistent.<\/li>\n<\/ol>\n<h3>2. Undersampling the majority class<\/h3>\n<p>Undersampling removes instances from the majority class until the class distribution matches that of the minority. This is useful when the majority class is overwhelmingly large and the dataset is still of manageable size. The RandomUnderSampler from the imblearn library offers a simple implementation.<\/p>\n<p>from imblearn.under_sampling import RandomUnderSamplerrus = RandomUnderSampler(sampling_strategy=&#8217;auto&#8217;, random_state=42)X_res_undersampled, y_res_undersampled = rus.fit_resample(    X_train_scaled, y_train)print(f&#8217;Original training set: {len(y_train)} samples&#8217;)print(f&#8217;Undersampled set: {len(y_res_undersampled)} samples&#8217;)print(&#8216;Class distribution after undersampling:&#8217;,      pd.Series(y_res_undersampled).value_counts())<\/p>\n<p>In the snippet:<\/p>\n<ul>\n<li>RandomUnderSampler is initialised with sampling_strategy=&#8217;auto&#8217;, which automatically balances all classes to the count of the minority class.<\/li>\n<li>fit_resample performs the undersampling and returns the resampled feature matrix and labels.<\/li>\n<li>Printing the sizes and class counts confirms that the majority class has been trimmed.<\/li>\n<\/ul>\n<h3>3. Oversampling the minority class<\/h3>\n<p>Oversampling duplicates minority instances until the desired balance is achieved. The RandomOverSampler is a quick way to do this, but it can lead to over\u2011fitting because it creates exact copies. Nevertheless, it is still widely used as a baseline.<\/p>\n<p>from imblearn.over_sampling import RandomOverSamplerros = RandomOverSampler(sampling_strategy=&#8217;auto&#8217;, random_state=42)X_res_oversampled, y_res_oversampled = ros.fit_resample(    X_train_scaled, y_train)print(&#8216;Class distribution after oversampling:&#8217;,      pd.Series(y_res_oversampled).value_counts())<\/p>\n<p>Here the logic mirrors undersampling: the sampler is fitted to the training data and returns a new dataset where each class contains an equal number of samples.<\/p>\n<h3>4. Applying SMOTE \u2013 generating synthetic minority samples<\/h3>\n<p>SMOTE constructs new minority samples by interpolating between existing minority instances. It mitigates the duplication problem inherent in plain oversampling. The standard SMOTE implementation from imblearn.over_sampling can be combined with a preprocessing pipeline for cleaner code.<\/p>\n<p>from imblearn.over_sampling import SMOTEfrom sklearn.pipeline import Pipelinefrom sklearn.ensemble import RandomForestClassifierfrom sklearn.metrics import classification_report<\/p>\n<h1>Define SMOTE with a 1:1 target ratio<\/h1>\n<p>smote = SMOTE(sampling_strategy=&#8217;auto&#8217;, random_state=42)<\/p>\n<h1>Build a pipeline: SMOTE \u2192 classifier<\/h1>\n<p>pipeline = Pipeline(steps=[    (&#8216;smote&#8217;, smote),    (&#8216;clf&#8217;, RandomForestClassifier(n_estimators=200, random_state=42))])<\/p>\n<h1>Train the pipeline on the original training data<\/h1>\n<p>pipeline.fit(X_train_scaled, y_train)<\/p>\n<h1>Predict on the untouched test set<\/h1>\n<p>y_pred = pipeline.predict(X_test_scaled)<\/p>\n<h1>Evaluate<\/h1>\n<p>print(classification_report(y_test, y_pred, target_names=le.classes_))<\/p>\n<p>Explanation of the pipeline:<\/p>\n<ol>\n<li>SMOTE is configured to resample until each class has the same number of instances.<\/li>\n<li>The RandomForestClassifier is a robust baseline model that tolerates noisy data.<\/li>\n<li>During fit, the pipeline first applies SMOTE to the training set, generating synthetic samples, then trains the classifier on this balanced data.<\/li>\n<li>Prediction is performed on the unaltered test set to assess real\u2011world performance.<\/li>\n<li>The classification_report shows precision, recall, f1\u2011score per class, allowing us to verify that the minority class has improved without an unacceptable drop in majority performance.<\/li>\n<\/ol>\n<h3>5. Comparing resampling strategies<\/h3>\n<p>It is useful to visualise the effect of each approach. The following table summarises the class distribution after each method, assuming a hypothetical dataset with three classes: healthy (10,000 samples), rust (1,200 samples), blight (800 samples).<\/p>\n<table>\n<thead>\n<tr>\n<th>Method<\/th>\n<th>healthy<\/th>\n<th>rust<\/th>\n<th>blight<\/th>\n<th>Total<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Original<\/td>\n<td>10,000<\/td>\n<td>1,200<\/td>\n<td>800<\/td>\n<td>12,000<\/td>\n<\/tr>\n<tr>\n<td>Undersampling (to minority)<\/td>\n<td>800<\/td>\n<td>800<\/td>\n<td>800<\/td>\n<td>2,400<\/td>\n<\/tr>\n<tr>\n<td>Oversampling (to majority)<\/td>\n<td>10,000<\/td>\n<td>10,000<\/td>\n<td>10,000<\/td>\n<td>30,000<\/td>\n<\/tr>\n<tr>\n<td>SMOTE (to majority)<\/td>\n<td>10,000<\/td>\n<td>10,000<\/td>\n<td>10,000<\/td>\n<td>30,000<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>As seen, SMOTE and plain oversampling produce identical class counts but differ in the nature of the minority samples \u2013 synthetic versus duplicated. Undersampling drastically reduces data volume, which may be undesirable if the dataset is already small.<\/p>\n<h3>6. Practical recommendations for crop disease datasets<\/h3>\n<ul>\n<li><strong>Start with SMOTE.<\/strong> Synthetic samples tend to improve generalisation because they introduce slight variations that mimic real disease spread.<\/li>\n<li><strong>Keep the test set untouched.<\/strong> Resampling should never be applied to the test material; otherwise you risk inflating performance metrics.<\/li>\n<li><strong>Check for feature leakage.<\/strong> When scaling before SMOTE, ensure that the scaler is fitted only on the training data; the code above follows this principle.<\/li>\n<li><strong>Monitor over\u2011fitting.<\/strong> If you observe a large gap between training and test f1\u2011scores, consider reducing the number of synthetic samples or switching to a more conservative oversampling method such as BorderlineSMOTE.<\/li>\n<li><strong>Use stratified cross\u2011validation.<\/strong> When evaluating models, stratify splits to preserve the original imbalance, then apply SMOTE within each fold.<\/li>\n<\/ul>\n<p>By integrating these resampling steps into your workflow, you can mitigate the detrimental effects of class imbalance on crop disease classifiers and achieve more reliable, deployable models.<\/p>\n<h3>7. Example: Adversarially Generated Synthetic Samples with ADASYN<\/h3>\n<p>While SMOTE interpolates between existing minority points, ADASYN (Adaptive Synthetic) focuses on difficult-to-learn examples by weighting the generation process towards samples that are harder to classify. This can improve performance when the minority class is highly heterogeneous.<\/p>\n<p>from imblearn.over_sampling import ADASYN<\/p>\n<h1>ADASYN with a target ratio of 1:1<\/h1>\n<p>adasyn = ADASYN(sampling_strategy=&#8217;auto&#8217;, random_state=42)X_res_adasyn, y_res_adasyn = adasyn.fit_resample(    X_train_scaled, y_train)print(&#8216;Class distribution after ADASYN:&#8217;,      pd.Series(y_res_adasyn).value_counts())<\/p>\n<h1>Train a simple SVM on the ADASYN\u2011balanced data<\/h1>\n<p>from sklearn.svm import SVCsvm_clf = SVC(kernel=&#8217;rbf&#8217;, class_weight=&#8217;balanced&#8217;, random_state=42)svm_clf.fit(X_res_adasyn, y_res_adasyn)y_pred_adasyn = svm_clf.predict(X_test_scaled)print(classification_report(y_test, y_pred_adasyn, target_names=le.classes_))<\/p>\n<p>Features of ADASYN:<\/p>\n<ul>\n<li>Generates more synthetic samples in regions where the minority class is sparse.<\/li>\n<li>Can reduce bias towards majority class by concentrating effort on hard cases.<\/li>\n<li>Often yields higher recall for the minority class at the cost of a modest precision drop.<\/li>\n<\/ul>\n<h3>8. Comparative Summary of Resampling Methods<\/h3>\n<p>The table below contrasts the key characteristics of undersampling, oversampling, SMOTE, BorderlineSMOTE, and ADASYN when applied to crop disease datasets.<\/p>\n<table>\n<thead>\n<tr>\n<th>Method<\/th>\n<th>Data Volume Change<\/th>\n<th>Risk of Over\u2011fitting<\/th>\n<th>Complexity of Synthetic Samples<\/th>\n<th>Typical Use\u2011case<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Random Undersampling<\/td>\n<td>\u2193 (reduces majority)<\/td>\n<td>Low<\/td>\n<td>None (removes real samples)<\/td>\n<td>Very large majority class, limited data<\/td>\n<\/tr>\n<tr>\n<td>Random Oversampling<\/td>\n<td>\u2191 (duplicates minority)<\/td>\n<td>High (exact duplicates)<\/td>\n<td>None (copies)<\/td>\n<td>Baseline, quick test<\/td>\n<\/tr>\n<tr>\n<td>SMOTE<\/td>\n<td>\u2191 (generates synthetic minority)<\/td>\n<td>Medium (interpolated)<\/td>\n<td>Linear interpolation<\/td>\n<td>Standard balanced training<\/td>\n<\/tr>\n<tr>\n<td>BorderlineSMOTE<\/td>\n<td>\u2191 (focuses on borderline samples)<\/td>\n<td>Medium (synthetic near decision boundary)<\/td>\n<td>Weighted interpolation<\/td>\n<td>When minority has hard boundaries<\/td>\n<\/tr>\n<tr>\n<td>ADASYN<\/td>\n<td>\u2191 (adaptive generation)<\/td>\n<td>Medium (focus on hard examples)<\/td>\n<td>Adaptive weighted interpolation<\/td>\n<td>Highly heterogeneous minority class<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span>Activity: Quick quiz on Resampling and SMOTE<\/span><\/p>\n<ol>\n<li>Which resampling technique can help to balance the majority and minority classes by duplicating minority samples?<\/li>\n<li>What does SMOTE stand for and how does it create synthetic samples?<\/li>\n<li>When using SMOTE, why is it important to apply it only to the training set and not to the test set?<\/li>\n<li>Which scikit\u2011learn function is used to perform random undersampling?<\/li>\n<\/ol>\n<h3>9. Alternative Mitigation: Synthetic Minority Over\u2011Sampling Technique (SMOTE)<\/h3>\n<p>SMOTE generates synthetic minority samples by interpolating between existing points in feature space.  For image data it is usually applied after feature extraction (e.g. after the flattening step) rather than directly on pixel arrays.<\/p>\n<p>from imblearn.over_sampling import SMOTE<\/p>\n<h1>Assume X_train_features is already defined<\/h1>\n<p>smote = SMOTE(random_state=42)X_smote, y_smote = smote.fit_resample(X_train_features, y_res)print(&#8216;After SMOTE:&#8217;, Counter(y_smote))<\/p>\n<p>SMOTE can increase diversity compared to simple duplication, but may introduce noise if the feature space is not well\u2011represented by a linear interpolation.<\/p>\n<table border=\"1\" cellpadding=\"4\" cellspacing=\"0\">\n<thead>\n<tr>\n<th>Approach<\/th>\n<th>How it Works<\/th>\n<th>Pros<\/th>\n<th>Cons<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Random Under\u2011Sampling<\/td>\n<td>Remove majority samples to balance<\/td>\n<td>Simple, reduces training time<\/td>\n<td>Potential loss of useful information<\/td>\n<\/tr>\n<tr>\n<td>Random Over\u2011Sampling<\/td>\n<td>Duplicate minority samples<\/td>\n<td>Preserves all data, easy to implement<\/td>\n<td>Risk of overfitting, larger training set<\/td>\n<\/tr>\n<tr>\n<td>SMOTE<\/td>\n<td>Generate synthetic minority points via interpolation<\/td>\n<td>More diverse than duplication, less overfitting<\/td>\n<td>Assumes linearity in feature space, may create noisy samples<\/td>\n<\/tr>\n<tr>\n<td>Class\u2011Weighting<\/td>\n<td>Adjust loss function to penalise minority errors more<\/td>\n<td>No change to data size, works with any model<\/td>\n<td>Requires careful tuning, may still be biased if imbalance severe<\/td>\n<\/tr>\n<tr>\n<td>Focal Loss<\/td>\n<td>Modifies cross\u2011entropy to focus on hard examples<\/td>\n<td>Effective for deep learning, handles imbalance implicitly<\/td>\n<td>More complex to implement, hyperparameter tuning needed<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span>Activity: Choosing the Right Resampling Strategy for Tomato Blight<\/span><\/p>\n<p>You have just completed the end\u2011to\u2011end pipeline for the tomato blight dataset, including preprocessing, feature engineering, and model training. Now, you need to decide how to handle the pronounced class imbalance (few infected leaves compared to healthy ones). Based on the techniques discussed in this lesson, outline which resampling method (undersampling, oversampling, SMOTE, or class\u2011weighting) you would apply, justify your choice, and describe how you would integrate it into the existing pipeline. Think about the impact on model performance, training time, and potential overfitting.<\/p>\n<h2>Pitfalls: Common Mistakes and How to Avoid Them<\/h2>\n<p>Handling class imbalance is a delicate balancing act. While resampling strategies, synthetic data generation and cost\u2011sensitive learning can greatly improve model performance, they also open the door to subtle errors that can undermine the entire project. In this section we dissect the most frequent mistakes that crop disease researchers make, analyse why they occur, and provide concrete guidance on how to sidestep them. By understanding these pitfalls we can design robust pipelines that genuinely improve detection of rare diseases rather than artefacts of data engineering.<\/p>\n<h3>1. Data Leakage During Resampling<\/h3>\n<p>Data leakage is arguably the most insidious source of over\u2011optimistic performance estimates. When resampling is performed without strict separation of training and test data, the model is inadvertently exposed to information that would not be available at inference time. This is particularly problematic in crop disease datasets where images are often grouped by field, time, or even camera. If the split is performed at the image level rather than at the field level, synthetic or augmented samples can leak across the boundary.<\/p>\n<p>Consider a scenario where a field contains 200 healthy and 20 diseased images. If we randomly select 10% of the images for the test set, we might end up with 2 diseased images in the test set. If we then apply SMOTE to the training data, SMOTE will generate synthetic samples based on the 18 diseased training images. Because the 2 test images share the same field and possibly the same visual characteristics, the synthetic samples will be highly correlated with the test set, leading to inflated performance metrics.<\/p>\n<p>To avoid leakage:<\/p>\n<ul>\n<li><strong>Split at the highest level of granularity<\/strong> (e.g. field, plot, or time period) before any resampling or augmentation.<\/li>\n<li><strong>Apply resampling only to the training split<\/strong> and keep the test set untouched.<\/li>\n<li><strong>Use nested cross\u2011validation<\/strong> where the inner loop performs resampling and hyper\u2011parameter optimisation, while the outer loop evaluates on a held\u2011out set that has never seen the resampled data.<\/li>\n<\/ul>\n<h3>2. Overfitting to Synthetic Samples<\/h3>\n<p>Generating synthetic data, whether through SMOTE, ADASYN or GANs, is often a double\u2011edged sword. While it can provide a more balanced class distribution, it can also create samples that are unnaturally similar to each other, especially when the minority class is very small. Models trained on such data may learn to recognise artefacts of the generation process rather than genuine disease markers.<\/p>\n<p>For example, a GAN trained on 30 diseased leaf images may produce synthetic leaves that share a specific texture pattern or colour gradient that is not present in real diseased samples. A convolutional neural network will then pick up on this artefact, yielding high accuracy on the synthetic\u2011augmented training set but poor generalisation to real field images.<\/p>\n<p>Mitigation strategies:<\/p>\n<ol>\n<li><strong>Limit the number of synthetic samples<\/strong> to a reasonable proportion of the minority class, e.g. 2\u20133 times the minority count, rather than oversaturating the training set.<\/li>\n<li><strong>Introduce diversity in augmentation<\/strong> by varying rotation, scaling, brightness, and contrast within realistic bounds.<\/li>\n<li><strong>Validate on a separate hold\u2011out set of real minority samples<\/strong> that were never used for synthetic generation.<\/li>\n<li><strong>Inspect synthetic samples visually<\/strong> and with domain experts to ensure they are plausible.<\/li>\n<\/ol>\n<p>Below is a concise example that demonstrates how to generate synthetic samples with SMOTE while carefully monitoring for overfitting. The code uses scikit\u2011learn\u2019s SMOTE and a simple logistic regression classifier. The training and validation loops are annotated to emphasise the separation of synthetic data from the test set.<\/p>\n<p>import numpy as npfrom sklearn.model_selection import train_test_splitfrom imblearn.over_sampling import SMOTEfrom sklearn.linear_model import LogisticRegressionfrom sklearn.metrics import classification_report, confusion_matrix<\/p>\n<h1>Assume X, y are pre\u2011processed feature matrices and labels<\/h1>\n<h1>Split into train+val and test at the field level<\/h1>\n<p>X_train_val, X_test, y_train_val, y_test = train_test_split(    X, y, test_size=0.2, stratify=y, random_state=42)<\/p>\n<h1>Further split training+validation into training and validation<\/h1>\n<p>X_train, X_val, y_train, y_val = train_test_split(    X_train_val, y_train_val, test_size=0.25, stratify=y_train_val, random_state=42)<\/p>\n<h1>1. Apply SMOTE only on the training data<\/h1>\n<p>smote = SMOTE(sampling_strategy=&#8217;auto&#8217;, random_state=42)X_train_res, y_train_res = smote.fit_resample(X_train, y_train)<\/p>\n<h1>2. Train a simple model on the resampled data<\/h1>\n<p>clf = LogisticRegression(max_iter=1000, random_state=42)clf.fit(X_train_res, y_train_res)<\/p>\n<h1>3. Evaluate on the untouched validation set<\/h1>\n<p>print(&#8220;Validation performance:&#8221;)print(classification_report(y_val, clf.predict(X_val)))<\/p>\n<h1>4. Final evaluation on the hold\u2011out test set<\/h1>\n<p>print(&#8220;Test performance:&#8221;)print(classification_report(y_test, clf.predict(X_test)))<\/p>\n<p><strong>Line\u2011by\u2011line explanation:<\/strong><\/p>\n<ul>\n<li>Lines 1\u20134 import the necessary libraries.<\/li>\n<li>Line 7 performs a field\u2011level split, ensuring that images from the same field are never shared between training and test sets.<\/li>\n<li>Line 12 further splits the training data into a smaller training set and a validation set, again preserving field boundaries.<\/li>\n<li>Line 17 instantiates SMOTE with the default strategy of balancing all classes to the majority count.<\/li>\n<li>Line 18 applies SMOTE only to the training subset, producing a new feature matrix X_train_res and labels y_train_res.<\/li>\n<li>Line 21 trains a logistic regression model on the resampled data.<\/li>\n<li>Lines 24\u201326 evaluate the model on the validation set, which contains no synthetic samples.<\/li>\n<li>Lines 29\u201331 provide the final test set evaluation, guaranteeing that the test data has never seen any synthetic or augmented samples.<\/li>\n<\/ul>\n<h3>3. Misinterpreting Accuracy on Imbalanced Data<\/h3>\n<p>Accuracy is a seductive metric: it is easy to compute and interpret. However, on highly imbalanced datasets it can give a misleading picture of model performance. Suppose a crop disease dataset contains 95% healthy leaves and 5% diseased leaves. A na\u00efve classifier that simply predicts every leaf as healthy will achieve 95% accuracy, yet it will miss all diseased cases.<\/p>\n<p>When using accuracy as a primary metric, one often overlooks the following:<\/p>\n<ul>\n<li>Accuracy does not capture the cost of false negatives, which in disease detection can mean missed outbreaks.<\/li>\n<li>It can mask poor recall for the minority class while boosting precision due to the overwhelming majority class.<\/li>\n<li>It is insensitive to the distribution of predictions when the minority class is rare.<\/li>\n<\/ul>\n<p>Instead, focus on metrics that are sensitive to class imbalance:<\/p>\n<ul>\n<li><strong>Precision, Recall and F1\u2011score<\/strong> for the minority class.<\/li>\n<li><strong>Area Under the Receiver Operating Characteristic curve (AUROC)<\/strong>, which evaluates ranking performance across thresholds.<\/li>\n<li><strong>Area Under the Precision\u2011Recall curve (AUPRC)<\/strong>, which is particularly informative when the minority class is rare.<\/li>\n<li>Confusion matrix visualisations to understand the distribution of true positives, false positives, true negatives and false negatives.<\/li>\n<\/ul>\n<p>When reporting results, present the full confusion matrix and the aforementioned metrics side by side. For example, a model with 92% accuracy but a minority class recall of 0.25 would be considered unusable for disease surveillance.<\/p>\n<h3>4. Inconsistent Evaluation Protocols<\/h3>\n<p>Another frequent mistake is the use of inconsistent evaluation protocols across studies or even within the same project. Some researchers report cross\u2011validated metrics, others report a single train\u2011test split, while still others report metrics on a held\u2011out dataset that was used for hyper\u2011parameter tuning. This inconsistency hampers reproducibility and makes it difficult to compare methods.<\/p>\n<p>Standardise your evaluation pipeline by:<\/p>\n<ul>\n<li>Using <strong>nested cross\u2011validation<\/strong> to separate hyper\u2011parameter optimisation from performance estimation.<\/li>\n<li>Keeping a <strong>final test set<\/strong> completely untouched until the very end.<\/li>\n<li>Documenting the exact train\u2011test split, random seeds, and preprocessing steps.<\/li>\n<li>Publishing the evaluation code and data splits alongside the manuscript.<\/li>\n<\/ul>\n<h3>5. Ignoring Temporal and Spatial Correlation<\/h3>\n<p>Crop disease datasets often exhibit strong temporal (seasonal) and spatial (field, region) dependencies. Treating all samples as independent can lead to over\u2011optimistic performance estimates. For instance, a model trained on data from one season may perform poorly in the next due to changes in disease prevalence or environmental conditions.<\/p>\n<p>Mitigation steps:<\/p>\n<ol>\n<li><strong>Stratify splits by season or spatial block<\/strong> to ensure that training and test sets span similar conditions.<\/li>\n<li><strong>Use time\u2011series cross\u2011validation<\/strong> where training data precedes test data chronologically.<\/li>\n<li><strong>Incorporate spatial features<\/strong> (e.g. GPS coordinates, elevation) into the model to capture locality effects.<\/li>\n<li>Perform <strong>domain adaptation<\/strong> techniques if deploying the model in a new region.<\/li>\n<\/ol>\n<h3>6. Over\u2011Engineering the Model Without Practical Benefit<\/h3>\n<p>It is tempting to add more layers, attention mechanisms or ensemble components to squeeze out every last point of performance. However, each added complexity increases the risk of overfitting, especially when the minority class is under\u2011represented. Moreover, in resource\u2011constrained deployment environments (e.g. edge devices on farms), a simpler model may be preferable.<\/p>\n<p>Adopt the <strong>Occam\u2019s Razor<\/strong> principle: favour the simplest model that achieves acceptable performance. Validate the necessity of each added component by ablation studies and monitor metrics such as inference time, memory footprint and energy consumption.<\/p>\n<h3>7. Neglecting Post\u2011Processing and Threshold Selection<\/h3>\n<p>Many practitioners default to a 0.5 probability threshold when converting model outputs to class labels. On imbalanced data this threshold is rarely optimal. A higher threshold may improve precision but hurt recall, and vice versa.<\/p>\n<p>To select an appropriate threshold:<\/p>\n<ul>\n<li>Plot the <strong>precision\u2011recall curve<\/strong> and choose a point that balances the two metrics according to the domain\u2019s cost function.<\/li>\n<li>Use <strong>cost\u2011sensitive learning<\/strong> to embed the relative cost of false positives and negatives into the optimisation objective.<\/li>\n<li>Apply <strong>calibration techniques<\/strong> (e.g. Platt scaling, isotonic regression) to ensure that predicted probabilities reflect true likelihoods.<\/li>\n<\/ul>\n<h3>8. Failing to Collaborate with Domain Experts<\/h3>\n<p>Technical solutions can only go so far without input from agronomists, plant pathologists and field technicians. Mislabelled data, subtle disease symptoms and context\u2011specific knowledge are often overlooked by purely data\u2011driven approaches.<\/p>\n<p>Engage experts at multiple stages:<\/p>\n<ul>\n<li>During <strong>data collection<\/strong> to ensure representative sampling.<\/li>\n<li>When <strong>label\u2011checking<\/strong> to verify that synthetic samples are realistic.<\/li>\n<li>During <strong>model interpretation<\/strong> to validate that the model is focusing on biologically plausible features.<\/li>\n<\/ul>\n<p>By integrating expert feedback, you reduce the risk of spurious correlations and improve the practical impact of your model.<\/p>\n<h3>9. Underestimating the Impact of Class Distribution on Loss Functions<\/h3>\n<p>Standard loss functions such as cross\u2011entropy treat all classes equally. When classes are imbalanced, the loss can be dominated by the majority class, causing the optimiser to prioritise it. One common remedy is to weight the loss inversely proportional to class frequencies.<\/p>\n<p>Example of a weighted cross\u2011entropy in PyTorch:<\/p>\n<p>import torchimport torch.nn as nn<\/p>\n<h1>Assume class_counts = [950, 50] for healthy and diseased<\/h1>\n<p>class_weights = torch.tensor([1.0, 19.0])  # 950\/50 = 19criterion = nn.CrossEntropyLoss(weight=class_weights)<\/p>\n<p>Here, the minority class receives a weight of 19, effectively emphasising its penalty during training. However, be cautious: overly large weights can destabilise training and lead to oscillations. It is advisable to perform a grid search over weight values and monitor validation metrics.<\/p>\n<h3>10. Ignoring the Ethical and Practical Implications of False Negatives<\/h3>\n<p>In crop disease detection, false negatives can have severe economic and food\u2011security consequences. A model that achieves high accuracy but misses a high\u2011severity disease outbreak may cause widespread crop loss.<\/p>\n<p>When designing the model, explicitly quantify the cost of false negatives. Use this cost to guide threshold selection, loss weighting and even the choice of evaluation metric. For instance, if the cost of missing a disease case is 10\u00d7 higher than a false alarm, a higher recall should be prioritised even at the expense of precision.<\/p>\n<p>Ultimately, the goal is to build a system that balances technical performance with real\u2011world impact. By recognising and avoiding the pitfalls outlined above, researchers can develop more reliable, generalisable, and ethically sound models for crop disease detection.<\/p>\n<h3>Additional Example: Using Class\u2011Weighted Focal Loss in a CNN<\/h3>\n<p>Focal loss is a popular choice for handling severe class imbalance in deep learning. It down\u2011weights easy examples and focuses the optimiser on hard, misclassified samples. Combining focal loss with class\u2011specific weighting further emphasises the minority class.<\/p>\n<p>import tensorflow as tffrom tensorflow import kerasfrom tensorflow.keras import layers<\/p>\n<h1>Assume class_counts = [950, 50] for healthy and diseased<\/h1>\n<p>class_weights = tf.constant([1.0, 19.0], dtype=tf.float32)def focal_loss(gamma=2.0):    def loss(y_true, y_pred):        # y_true: one\u2011hot encoded, y_pred: logits        y_true = tf.cast(y_true, dtype=tf.float32)        y_pred = tf.cast(y_pred, dtype=tf.float32)        cross_entropy = tf.nn.softmax_cross_entropy_with_logits(            labels=y_true, logits=y_pred)        probs = tf.nn.softmax(y_pred)        focal_weight = tf.pow(1.0 &#8211; tf.reduce_sum(probs * y_true, axis=-1), gamma)        weighted_ce = focal_weight * cross_entropy        # Apply class\u2011specific weights        class_weight = tf.reduce_sum(y_true * class_weights, axis=-1)        return tf.reduce_mean(weighted_ce * class_weight)    return lossmodel = keras.Sequential([    layers.Conv2D(32, 3, activation=&#8217;relu&#8217;, input_shape=(224, 224, 3)),    layers.MaxPooling2D(),    layers.Conv2D(64, 3, activation=&#8217;relu&#8217;),    layers.MaxPooling2D(),    layers.Flatten(),    layers.Dense(2)])model.compile(optimizer=&#8217;adam&#8217;,              loss=focal_loss(gamma=2.0),              metrics=[&#8216;accuracy&#8217;])<\/p>\n<p>Table 1 compares the key properties of three common approaches to class imbalance in crop disease detection.<\/p>\n<table border=\"1\" cellpadding=\"4\" cellspacing=\"0\">\n<thead>\n<tr>\n<th>Approach<\/th>\n<th>Primary Technique<\/th>\n<th>Pros<\/th>\n<th>Cons<\/th>\n<th>Typical Use\u2011Case<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Resampling (SMOTE, ADASYN)<\/td>\n<td>Feature\u2011space oversampling<\/td>\n<td>Simple to implement; balances class distribution<\/td>\n<td>Risk of overfitting; may not preserve original data distribution<\/td>\n<td>Small\u2011to\u2011medium datasets where feature extraction is stable<\/td>\n<\/tr>\n<tr>\n<td>Cost\u2011Sensitive Loss (Weighted CE, Focal Loss)<\/td>\n<td>Modify training objective<\/td>\n<td>Preserves original data; directly optimises for minority class<\/td>\n<td>Requires careful tuning of weights; can destabilise training<\/td>\n<td>Large\u2011scale deep learning models with high imbalance<\/td>\n<\/tr>\n<tr>\n<td>Ensemble &amp; Threshold Tuning<\/td>\n<td>Combine multiple models; adjust decision threshold<\/td>\n<td>Improves robustness; flexible to different costs<\/td>\n<td>Computationally expensive; complex to maintain<\/td>\n<td>Operational deployments where inference cost is acceptable<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span>Activity: Discuss Common Pitfalls in Handling Class Imbalance<\/span><\/p>\n<p>Reflect on the pitfalls highlighted in the section on common mistakes. What are the most frequent errors you have encountered or heard about when dealing with class imbalance in crop disease datasets, and how can you mitigate them? Share examples from your own projects or research to illustrate your points.<\/p>\n<h3>Key Takeaways<\/h3>\n<ul>\n<li>Explain why class imbalance can bias machine learning models in crop disease detection.<\/li>\n<li>Identify and compare common techniques for mitigating class imbalance, such as resampling, cost-sensitive learning, and synthetic data generation.<\/li>\n<li>Implement imbalance handling strategies using Python and scikit\u2011learn in a crop disease dataset.<\/li>\n<li>Evaluate the impact of imbalance mitigation on model performance metrics and recognise common pitfalls.<\/li>\n<\/ul>\n<h3>Further Reading<\/h3>\n<ul>\n<li><strong>James, G., Witten, D., Hastie, T. &amp; Tibshirani, R. (2013)<\/strong> \u2014 Modern Applied Statistics with S. A foundational text covering resampling techniques and class\u2011weight adjustments for imbalanced data.<\/li>\n<li><strong>Chawla, N.V., Bowyer, K.W., Hall, L.O. &amp; Kegelmeyer, W.P. (2002)<\/strong> \u2014 \u201cSMOTE: Synthetic Minority Over-sampling Technique\u201d. Journal of Artificial Intelligence Research. Introduces a widely used oversampling method for medical and agricultural datasets.<\/li>\n<li><strong>Fawcett, T. (2006)<\/strong> \u2014 \u201cAn introduction to ROC analysis\u201d. Pattern Recognition Letters. Provides metrics such as ROC curves and AUC to evaluate classifiers on imbalanced crop disease data.<\/li>\n<li><strong>Hughes, J.P. (2020)<\/strong> \u2014 \u201cMachine Learning for Precision Agriculture\u201d. Springer. Discusses class\u2011imbalance strategies specific to plant disease image datasets.<\/li>\n<li><strong>Scikit\u2011Learn Documentation (2025)<\/strong> \u2014 \u201cImbalanced-learn integration\u201d. Official guide for applying resampling, weighting and ensemble techniques in Python.<\/li>\n<li><strong>International Plant Protection Convention (IPPC) (2022)<\/strong> \u2014 \u201cGuidelines for Data Standards in Plant Health Monitoring\u201d. Offers recommended practices for handling uneven disease occurrence data.<\/li>\n<\/ul>\n<p>[tcb-script src=&#8221;https:\/\/cdn.jsdelivr.net\/npm\/mermaid@10\/dist\/mermaid.min.js&#8221;][\/tcb-script][tcb-script](function() {  try { if (window.mermaid) { window.mermaid.initialize({ startOnLoad: true, theme: &#8216;default&#8217; }); } } catch(e){}  var supported = !!window.HTMLDetailsElement;  if (!supported) {    document.querySelectorAll(&#8216;.moodlecraft-lesson details&#8217;).forEach(function(d) {      var s = d.querySelector(&#8216;summary&#8217;); if (!s) return;      var kids = Array.from(d.children).filter(function(c){return c!==s;});      kids.forEach(function(el){el.style.display=&#8217;none&#8217;;});      s.addEventListener(&#8216;click&#8217;, function(e){        e.preventDefault();        var open = d.hasAttribute(&#8216;open&#8217;);        kids.forEach(function(el){el.style.display = open?&#8217;none&#8217;:&#8217;block&#8217;;});        if(open){d.removeAttribute(&#8216;open&#8217;);} else {d.setAttribute(&#8216;open&#8217;,&#8221;);}      });    });  }})();[\/tcb-script]<\/p>\n","protected":false},"template":"","class_list":["post-105942","tva_lesson","type-tva_lesson","status-publish","hentry","tva_courses-ai-for-crop-disease-detection-using-hyperspectral-imaging","post-wrapper","thrv_wrapper"],"acf":[],"_links":{"self":[{"href":"https:\/\/staging.nanoschool.in\/wp\/wp-json\/wp\/v2\/tva_lesson\/105942","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/staging.nanoschool.in\/wp\/wp-json\/wp\/v2\/tva_lesson"}],"about":[{"href":"https:\/\/staging.nanoschool.in\/wp\/wp-json\/wp\/v2\/types\/tva_lesson"}],"wp:attachment":[{"href":"https:\/\/staging.nanoschool.in\/wp\/wp-json\/wp\/v2\/media?parent=105942"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}