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.
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
$ 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}
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.
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.
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.