Вернуться на страницу brain2net: https://brain2net.ru/post/logisticheskaya-regressiya/#more-196

Логистическая регрессия

In [35]:
from sklearn.linear_model import LogisticRegression 
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt

Премер с iris

In [2]:
# Загрузить данные только с двумя классами 
iris = datasets.load_iris()
features = iris.data[:100,:] 
target = iris.target[:100]
In [3]:
target
Out[3]:
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
In [4]:
# Стандартизировать признаки 
scaler = StandardScaler()
features_standardized = scaler.fit_transform(features)
In [5]:
# Создать объект логистической регрессии 
logistic_regression = LogisticRegression(random_state=0)
In [6]:
# Натренировать модель
model = logistic_regression.fit(features_standardized, target)
In [7]:
# Создать новое наблюдение 
new_observation = [[5.1, 3.5, 1.4, 0.2]]
new_observation_standardized = scaler.transform(new_observation)

new_observation_standardized
Out[7]:
array([[-0.5810659 ,  0.84183714, -1.01297765, -1.04211089]])
In [8]:
new_observation
Out[8]:
[[5.1, 3.5, 1.4, 0.2]]
In [9]:
# Предсказать класс
model.predict(new_observation_standardized)
Out[9]:
array([0])
In [10]:
# Оценить предсказанные вероятности 
model.predict_proba(new_observation)
Out[10]:
array([[0.05885798, 0.94114202]])

То же но с разделением выборки на обучающую и тестовую

In [11]:
# Загрузить данные только с двумя классами 
iris = datasets.load_iris()
features = iris.data[:100,:] 
target = iris.target[:100]
In [12]:
# Стандартизировать признаки 
scaler = StandardScaler()
features_standardized = scaler.fit_transform(features)
In [13]:
X_train, X_test, y_train, y_test = \
train_test_split(features_standardized, target, random_state=42)
In [14]:
oper = LogisticRegression(random_state=0).fit(X_train, y_train)
In [15]:
print("Правильность на обучающем наборе: {:.2f}".format(oper.score(X_train, y_train)))
print("Правильность на тестовом наборе: {:.2f}".format(oper.score(X_test, y_test)))
Правильность на обучающем наборе: 1.00
Правильность на тестовом наборе: 1.00

Пример с breast_cancer

In [19]:
from sklearn.datasets import load_breast_cancer
cancer = load_breast_cancer()
X_train, X_test, y_train, y_test = \
train_test_split(cancer.data, cancer.target, stratify=cancer.target, random_state=42)
In [24]:
logreg = LogisticRegression(max_iter=10000).fit(X_train, y_train)
print("Правильность на обучающем наборе: {:.3f}".format(logreg.score(X_train, y_train)))
print("Правильность на тестовом наборе: {:.3f}".format(logreg.score(X_test, y_test)))
Правильность на обучающем наборе: 0.958
Правильность на тестовом наборе: 0.958

Было необходимо увеличить количество итераций - max_iter. При количестве итераций по умолчанию выдавалось предупреждение.

Значение по умолчанию C=1 обеспечивает неплохое качество модели, правильность на обучающем и тестовом наборах составляет 95%.

Однако поскольку качество модели на обучающем и тестовом наборах примерно одинако, вполне вероятно, что мы недообучили модель.

In [25]:
logreg100 = LogisticRegression(max_iter=10000, C=100).fit(X_train, y_train)
print("Правильность на обучающем наборе: {:.3f}".format(logreg100.score(X_train, y_train)))
print("Правильность на тестовом наборе: {:.3f}".format(logreg100.score(X_test, y_test)))
Правильность на обучающем наборе: 0.979
Правильность на тестовом наборе: 0.965

Использование C=100 привело к более высокой правильности на обучающей выборке, а также немного увеличилась правильность на тестовой выборке, что подтверждает наш довод о том, что более сложная модель должна сработать лучше.

Регуляризация L1

При солвере по умолчанию solver='lbfgs' может использоваться только L2.

Warning The choice of the algorithm depends on the penalty chosen: Supported penalties by solver:

‘newton-cg’ - [‘l2’, ‘none’]

‘lbfgs’ - [‘l2’, ‘none’]

‘liblinear’ - [‘l1’, ‘l2’]

‘sag’ - [‘l2’, ‘none’]

‘saga’ - [‘elasticnet’, ‘l1’, ‘l2’, ‘none’]

In [39]:
for C, marker in zip([0.001, 1, 100], ['o', '^', 'v']):
    lr_l1 = LogisticRegression(max_iter=10000, C=C, solver='liblinear', penalty='l1').fit(X_train, y_train)
    print("Правильность на обучении для логрегрессии l1 с C={:.3f}: {:.2f}".format(
        C, lr_l1.score(X_train, y_train)))
    print("Правильность на тесте для логрегрессии l1 с C={:.3f}: {:.2f}".format(
        C, lr_l1.score(X_test, y_test)))
    plt.plot(lr_l1.coef_.T, marker, label="C={:.3f}".format(C))
    plt.xticks(range(cancer.data.shape[1]), cancer.feature_names, rotation=90)
    plt.hlines(0, 0, cancer.data.shape[1])
    plt.xlabel("Индекс коэффициента")
    plt.ylabel("Оценка коэффициента")
plt.ylim(-5, 5)
plt.legend(loc=3)
Правильность на обучении для логрегрессии l1 с C=0.001: 0.91
Правильность на тесте для логрегрессии l1 с C=0.001: 0.92
Правильность на обучении для логрегрессии l1 с C=1.000: 0.96
Правильность на тесте для логрегрессии l1 с C=1.000: 0.96
Правильность на обучении для логрегрессии l1 с C=100.000: 0.99
Правильность на тесте для логрегрессии l1 с C=100.000: 0.98
Out[39]:
<matplotlib.legend.Legend at 0x17198644348>

Примечание. При выводе коэффициентов использовано транспонирование матрицы - lrl1.coef.T

Вернуться на страницу brain2net: https://brain2net.ru/post/logisticheskaya-regressiya/#more-196