BACK_TO_LOGS// STEP_6_OF_10
HANDBOOK_GUIDE2026-06-29

OptiCrop: Smart Agricultural Production Optimization Engine ML Guide

By Rayan Syed
45 min read

Part 6: Production Script - Model Comparison & Training (train.py)

We now transition from interactive notebook exploration to writing a production-grade Python script named train.py. While Jupyter is excellent for visual exploration (EDA) and prototype cleaning, standard Python scripts are preferred in production environments to run training pipelines from end to end and save the resulting model files.

6.1 Understanding Machine Learning Models & Algorithms

In this script, we train and compare four distinct classification models to find the one that balances accuracy with minority class detection:

  • Logistic Regression: A linear model that estimates the probability of crop suitability scores. It is fast and simple.
  • K-Nearest Neighbors (KNN): A distance-based classifier that looks at the 5 most similar historical soil records to vote on the crop.
  • Decision Tree Classifier: A tree model that splits parameters recursively using simple True/False check paths.
  • Random Forest Classifier: An ensemble model that builds 100 decision trees and averages their outputs. It is highly robust, handles non-linear relationships, and reduces variance.
  • K-Means Clustering: An unsupervised learning algorithm that groups similar soil and weather profiles into 5 macro categories, helping researchers spot regional patterns without using labels.

Model Comparison Training Script (train.py)

Save this complete script as train.py in your project root folder:

import os
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.cluster import KMeans
from sklearn.metrics import accuracy_score, classification_report
import joblib

def run_training_pipeline():
    print("Step 1: Loading agricultural dataset...")
    df = pd.read_csv('data/Crop_recommendation.csv')

    print("Step 2: Resolving missing values...")
    # Fill any empty cells with median values
    for col in df.columns[:-1]:
        if df[col].isnull().sum() > 0:
            df[col] = df[col].fillna(df[col].median())

    # Split features and target
    X = df.drop(columns=['label'])
    y = df['label']

    # Stratified split to keep crop proportions identical
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)

    print("Step 3: Applying Standard Scaling to features...")
    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train)
    X_test_scaled = scaler.transform(X_test)

    print("\nStep 4: Training and comparing classification models...")
    models = {
        "Logistic Regression": LogisticRegression(max_iter=1500, random_state=42),
        "K-Nearest Neighbors": KNeighborsClassifier(n_neighbors=5),
        "Decision Tree": DecisionTreeClassifier(random_state=42),
        "Random Forest": RandomForestClassifier(n_estimators=100, random_state=42)
    }

    best_acc = 0.0
    best_model = None
    best_model_name = ""

    for name, clf in models.items():
        # Fit classifier
        clf.fit(X_train_scaled, y_train)
        y_pred = clf.predict(X_test_scaled)
        
        acc = accuracy_score(y_test, y_pred)
        print(f"-> {name} Test Accuracy: {acc * 100:.2f}%")
        
        if acc > best_acc:
            best_acc = acc
            best_model = clf
            best_model_name = name

    # Unsupervised K-Means clustering check
    kmeans = KMeans(n_clusters=5, random_state=42, n_init=10)
    kmeans.fit(X_train_scaled)
    print("\nUnsupervised K-Means clustering completed on scaled features.")

    print(f"\nWinner Selected: {best_model_name} with {best_acc * 100:.2f}% accuracy.")
    
    # Print metrics report for the winner
    winner_preds = best_model.predict(X_test_scaled)
    print("\nWinner Performance Report:")
    print(classification_report(y_test, winner_preds))

    print("Step 5: Serializing and saving best model & scaler...")
    os.makedirs('models', exist_ok=True)
    joblib.dump(best_model, 'models/crop_model.joblib')
    joblib.dump(scaler, 'models/scaler.joblib')
    print("✓ Output model: models/crop_model.joblib")
    print("✓ Output scaler: models/scaler.joblib")

if __name__ == '__main__':
    run_training_pipeline()

6.2 Executing the Training Script

  • Open your project terminal and run:
    python train.py
    
  • Expected Output: The terminal will print out step-by-step progress, output accuracy percentages for each classifier, print the final classification metrics report, and confirm the serialization of the winning model.