How to train logistic regression with scikit-learn

Logistic regression is a linear classification baseline for labeled data with numeric features. In scikit-learn, LogisticRegression fits class boundaries through the standard estimator interface, so a fitted object can score held-out rows, predict labels, and return class probabilities before the project compares tree-based or kernel models.

A pipeline keeps scaling and classification together when numeric features need preprocessing before fitting. StandardScaler learns its mean and scale from the training split only, and LogisticRegression receives transformed training and test rows through the same estimator object.

The Iris dataset keeps the training run small while still exercising multiclass classification. A stratified train/test split preserves the label mix, and the held-out accuracy plus a sample probability vector show that the fitted model can classify rows it did not see during fitting.

Steps to train a scikit-learn logistic regression model:

  1. Save a training script that splits the data, fits a scaled logistic regression pipeline, and prints held-out accuracy, class labels, coefficient shape, and a sample prediction.
    train_logistic_regression.py
    from sklearn.datasets import load_iris
    from sklearn.linear_model import LogisticRegression
    from sklearn.metrics import accuracy_score
    from sklearn.model_selection import train_test_split
    from sklearn.pipeline import make_pipeline
    from sklearn.preprocessing import StandardScaler
     
     
    iris = load_iris()
    X_train, X_test, y_train, y_test = train_test_split(
        iris.data,
        iris.target,
        test_size=0.25,
        stratify=iris.target,
        random_state=42,
    )
     
    model = make_pipeline(
        StandardScaler(),
        LogisticRegression(max_iter=200),
    )
    model.fit(X_train, y_train)
     
    predictions = model.predict(X_test)
    accuracy = accuracy_score(y_test, predictions)
    classifier = model.named_steps["logisticregression"]
     
    sample_prediction = model.predict(X_test[[0]])[0]
    sample_probability = model.predict_proba(X_test[[0]])[0]
    sample_probabilities = {
        str(iris.target_names[index]): round(float(probability), 3)
        for index, probability in enumerate(sample_probability)
    }
     
    print(f"train rows: {X_train.shape[0]}")
    print(f"test rows: {X_test.shape[0]}")
    print(f"accuracy: {accuracy:.3f}")
    print(f"classes: {', '.join(iris.target_names[classifier.classes_])}")
    print(f"coefficient shape: {classifier.coef_.shape}")
    print(f"first prediction: {iris.target_names[sample_prediction]}")
    print(f"first probabilities: {sample_probabilities}")

    The pipeline keeps scaling and classification in one fitted object, so fit() learns scaling values from X_train and predict() applies the same transform to held-out rows.
    Related: How to create a scikit-learn pipeline
    Related: How to standardize features with scikit-learn

  2. Run the training script.
    $ python3 train_logistic_regression.py
    train rows: 112
    test rows: 38
    accuracy: 0.921
    classes: setosa, versicolor, virginica
    coefficient shape: (3, 4)
    first prediction: setosa
    first probabilities: {'setosa': 0.985, 'versicolor': 0.015, 'virginica': 0.0}
  3. Check that the training and test row counts match the split.

    The Iris dataset has 150 rows. With test_size=0.25, the stratified split keeps 112 rows for fitting and 38 rows for held-out scoring.

  4. Verify the class labels and coefficient shape.

    The three class labels match the Iris target names, and coefficient shape: (3, 4) means the model learned one four-feature coefficient row for each class.

  5. Confirm the sample prediction and probability output.

    predict() returns the top class label for the first held-out row. predict_proba() shows the class probabilities behind that decision, with setosa receiving 0.985.