The scikit library has several ways to perform binary classification. Weirdly, there are two different ways to use logistic regression. The LogisticRegression class uses matrix operations (L-BFGS algorithm by default) or SGD (actually SAG — Stochastic Average Gradient) to train a model. The SGDClassifier class is multipurpose and is a strangely-designed wrapper over several binary classification algorithms, one of which is logistic regression that is trained using stochastic gradient descent.
Put another way: LogisticRegression solves only logistic regression problems using one of several algorithms, including a variant of SGD. SGDClassifier solves several different types of problems, all using SGD.
I experimented with SGDClassifier. I used one of my standard datasets where the goal is to predict sex (male = 0, female = 1) from age, State, income, and political leaning. The data looks like:
+1 0.24 1 0 0 0.2950 0 0 1 -1 0.39 0 0 1 0.5120 0 1 0 +1 0.63 0 1 0 0.7580 1 0 0 -1 0.36 1 0 0 0.4450 0 1 0 . . .
The columns are sex, age divided by 100, State (Michigan = 100, Nebraska = 010, Okahoma = 001), income divided by $100,000, and politics (conservative = 100, moderate = 010, liberal = 001). There is 200 training items and 40 test items. The data can be found at jamesmccaffrey.wordpress.com/2022/09/23/binary-classification-using-pytorch-1-12-1-on-windows-10-11/.
The key statements that create and train a logistic regression model are:
print("Creating SGD logistic regression model")
model = SGDClassifier(loss='log', penalty=None,
alpha=0.0001, max_iter=1000, tol=0.00001, shuffle=True,
verbose=0, random_state=1, learning_rate='optimal',
eta0=0.0)
model.fit(train_X, train_y)
When you specify loss=’log’ you implicitly create a logistic regression model. If you use a different loss type, you create a different model. For example, loss=’hinge’ creates a SVM (support vector machine) model. This is a very poor API design.
The SGDClassifier has a lot of parameters, many of which are somewhat confusing. For example, learning_rate=’optimal’ type ignores the initial learning rate value of eta0.
The SGDClassifier is extremely sensitive to its parameter values. It took me about 3 hours of trying different combinations of values to get reasonable results of 84.00% accuracy on the training data and 72.50% accuracy on the test data.
Note: See my example of using the scikit LogisticRegression class at https://jamesmccaffreyblog.com/2023/01/24/revisiting-binary-classification-using-scikit-logistic-regression/.

When I worked on a cruise ship, one of my favorite ports was Venice. The Venice carnival runs for two weeks in February. I think the Venice carnival costumes, with their gradient colors, are beautiful.
Demo code. Replace “lt” (less–than) with Boolean operator symbol.
# people_gender_sgd.py
# predict gender (0 = male), 1 = female)
# from age, State, income, job-type
# uses scikit SGD version of logistic regression
# data:
# 1 0.24 1 0 0 0.2950 0 0 1
# 0 0.39 0 0 1 0.5120 0 1 0
# 1 0.27 0 1 0 0.2860 0 0 1
# . . .
# Anaconda3-2020.02 Python 3.7.6
# Windows 10/11
import numpy as np
from sklearn.linear_model import SGDClassifier
from sklearn.metrics import precision_score
import pickle
def show_confusion(cm):
# Confusion matrix whose i-th row and j-th column entry
# indicates the number of samples with true label being
# i-th class and predicted label being j-th class.
ct_act0_pred0 = cm[0][0] # TN
ct_act0_pred1 = cm[0][1] # FP wrongly predicted as pos
ct_act1_pred0 = cm[1][0] # FN wrongly predicted as neg
ct_act1_pred1 = cm[1][1] # TP
print("actual 0 | %4d %4d" % (ct_act0_pred0, ct_act0_pred1))
print("actual 1 | %4d %4d" % (ct_act1_pred0, ct_act1_pred1))
print(" ----------")
print("predicted 0 1")
# -----------------------------------------------------------
def main():
# 0. get ready
print("\nBegin scikit logistic regression SGD learning ")
np.random.seed(1)
# 1. load data
print("\nLoading data into memory ")
train_file = ".\\Data\\people_train.txt"
train_xy = np.loadtxt(train_file, usecols=range(0,9),
delimiter="\t", comments="#", dtype=np.float32)
train_X = train_xy[:,1:9]
train_y = train_xy[:,0].astype(int)
test_file = ".\\Data\\people_test.txt"
test_xy = np.loadtxt(test_file, usecols=range(0,9),
delimiter="\t", comments="#", dtype=np.float32)
test_X = test_xy[:,1:9]
test_y = test_xy[:,0].astype(int)
print("\nTraining data:")
print(train_X[0:4])
print(". . . \n")
print(train_y[0:4])
print(". . . ")
# 2. create model and train
# SGDClassifier(loss='hinge', *, penalty='l2', alpha=0.0001,
# l1_ratio=0.15, fit_intercept=True, max_iter=1000,
# tol=0.001, shuffle=True, verbose=0, epsilon=0.1,
# n_jobs=None, random_state=None, learning_rate='optimal',
# eta0=0.0, power_t=0.5, early_stopping=False,
# validation_fraction=0.1, n_iter_no_change=5,
# class_weight=None, warm_start=False, average=False)
# loss{'hinge', 'log_loss', 'log', 'modified_huber',
# 'squared_hinge', 'perceptron', 'squared_error', 'huber',
# 'epsilon_insensitive', 'squared_epsilon_insensitive'},
# default='hinge'
print("\nCreating SGD logistic regression model")
model = SGDClassifier(loss='log', penalty=None,
alpha=0.0001, max_iter=1000, tol=0.00001, shuffle=True,
verbose=0, random_state=1, learning_rate='optimal',
eta0=0.0)
model.fit(train_X, train_y)
# 3. evaluate
print("\nComputing model accuracy ")
acc_train = model.score(train_X, train_y)
print("Accuracy on training = %0.4f " % acc_train)
acc_test = model.score(test_X, test_y)
print("Accuracy on test = %0.4f " % acc_test)
# 4. make a prediction
print("\nPredict age 36, Oklahoma, $50K, moderate ")
X = np.array([[0.36, 0,0,1, 0.5000, 0,1,0]],
dtype=np.float32)
p = model.predict_proba(X)
p = p[0][1] # first (only) row, second value P(1)
print("\nPrediction prob = %0.6f " % p)
if p "lt" 0.5:
print("Prediction = male ")
else:
print("Prediction = female ")
# 5. save model
# print("\nSaving trained logistic regression model ")
# path = ".\\Models\\people_scikit_model.sav"
# pickle.dump(model, open(path, "wb"))
# 6. confusion matrix with labels
y_predicteds = model.predict(test_X)
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(test_y, y_predicteds)
print("\nConfusion matrix custom: ")
show_confusion(cm)
print("\nEnd People logistic regression demo ")
if __name__ == "__main__":
main()

.NET Test Automation Recipes
Software Testing
SciPy Programming Succinctly
Keras Succinctly
R Programming
Visual Studio Live
Microsoft MLADS Conference
DevIntersection Conference
Machine Learning Week
Ai4 Conference
G2E Conference
iSC West Conference
You must be logged in to post a comment.