import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
class LogisticRegression:
def __init__(self):
self.coef_ = None
self.intercept_ = None
self._theta = None
def _sigmoid(self, t):
return 1 / (1 + np.exp(-t))
def fit(self, x_train, y_trian, n):
def J(theta, x_b, y):
y_hat = self._sigmoid(x_b.dot(theta))
return -np.sum(y * np.log(y_hat) + (1 - y) * np.log(1 - y_hat)) / len(y)
def dJ(theta, x_b, y):
return x_b.T.dot(self._sigmoid(x_b.dot(theta)) - y) / len(y)
def gradient_descent(x_b, y, initial_theta, alpha=0.01, n_iters=1e4, epsilon=1e-8):
theta = initial_theta
iter = 0
while iter < n_iters:
gradient = dJ(theta, x_b, y)
last_theta = theta
theta = theta - alpha * gradient
if abs(J(last_theta, x_b, y) - J(theta, x_b, y)) < epsilon:
break
iter += 1
return last_theta
x_b = np.hstack([np.ones((len(x_train), 1)), x_train])
initail_theta = np.zeros(x_b.shape[1])
self._theta = gradient_descent(x_b, y_trian, initail_theta, n_iters=n)
self.intercept_ = self._theta[0]
self.coef_ = self._theta[1:]
def predict_prob(self, x_test):
x_b = np.hstack([np.ones((len(x_test), 1)), x_test])
return self._sigmoid(x_b.dot(self._theta))
def predict(self, x_test):
prob = self.predict_prob(x_test)
return np.array(prob >= 0.5,dtype='int')
def score(self, x_test, y_test):
return np.sum(y_test == self.predict(x_test)) / len(y_test)
# 鸢尾花数据集测试手写逻辑回归算法
iris = load_iris()
x = iris.data
y = iris.target
# 由于逻辑回归只能处理2分类问题,截取分类为0,1,保留x2个特征方便可视化
X = x[y < 2, :2]
Y = y[y < 2]
plt.scatter(X[Y == 0, 0], X[Y == 0, 1])
plt.scatter(X[Y == 1, 0], X[Y == 1, 1], color='r')
plt.show()
x_train, x_test, y_train, y_test = train_test_split(X, Y)
logistic = LogisticRegression()
logistic.fit(x_train, y_train, n=1e6)
y_predict = logistic.predict(x_test)
score = logistic.score(x_test, y_test)
print(score)
print(y_predict)
print(y_test)