Анализ принципов логистической регрессии и реализация Python

искусственный интеллект Python регулярное выражение NumPy

1. Анализ принципа логистической регрессии

Целевая функция (сигмовидная функция):

p(y=1|x;\theta)=h_\theta(x)=\frac{1}{1+\exp(\theta^Tx)}

Здесь \theta — параметр модели, то есть коэффициент регрессии, а \sigma — сигмоидальная функция. Таким образом, «вероятность» y = 0:

p(y=0|x;\theta)=1-h_\theta(x)=\frac{exp(\theta^Tx)}{1+exp(\theta^Tx)}

Для логистической регрессии логарифмические шансы получаются следующим образом:

log(\frac{h_\theta(x)}{1-h_\theta(x)})=\theta_0+\theta_1x_1+\cdots+\theta_mx_m

Во время обучения параметра для его решения можно использовать метод оценки максимального правдоподобия. Предположим, у нас есть n независимых обучающих выборок {(x1, y1), (x2, y2),..., (xn, yn)}, y={0, 1}. Вероятность появления каждой наблюдаемой выборки (xi, yi):

p(y^{(i)},x^{(i)})=p(y^{(i)}=1|x^{(i)})^{y^{(i)}}(1-p(y^{(i)}=1|x^{(i)}))^{1-y^{(i)}}

Для всего набора выборок появление каждой выборки независимо, а функция правдоподобия появления n выборок равна (вероятность появления n выборок является произведением их соответствующих вероятностей):

L(\theta)=\prod p(y^{(i)},x^{(i)})=\prod p(y^{(i)}=1|x^{(i)})^{y^{(i)}}(1-p(y^{(i)}=1|x^{(i)}))^{1-y^{(i)}}

Логарифмическая функция правдоподобия:

logit(\theta)=\sum (y^{(i)} logh_\theta(x^{(i)}) + (1-y^{(i)}) log(1-h_\theta(x^{(i)})) )

Мы хотим найти параметр θ, который максимизирует функцию logit(θ), поэтому мы устанавливаем функцию стоимости модели как:

l(\theta)=-logit(\theta)

Таким образом, определение оптимального параметра \theta может быть преобразовано в поиск функции минимальной стоимости l(\theta).

2. Метод градиентного спуска

1) Параметр инициализации \theta=(0,\theta_1,\theta_2,…,\theta_n )^T, начальное значение \theta=(0, 0, 0, …, 0 )^T

2) Получите образец X, добавьте 1 перед каждым образцом, x=(1,x_1,x_2,…,x_n )^T

3) Установите размер шага α

4) Используйте сигмовидную функцию, чтобы предсказать выборку

5) Рассчитайте градиент в соответствии с функцией логарифмического правдоподобия g=\nabla_\theta l(\theta)

6) Обновить параметр \theta=\theta-\alpha g

Повторяйте шаги 4-6 до тех пор, пока точность результата не будет соответствовать требованиям, или итерация завершится, когда будет достигнуто определенное количество раз.

При добавлении обычных терминов

Функция стоимости добавляет обычный член l(\theta)=-logit(\theta)+\frac{\lambda}{2m}\sum_{j=1}^m\theta_j^2

Таким образом, шаг 5 изменяется на g=\nabla_\theta l(\theta)+\frac{\lambda}{m}\theta

3. Метод Ньютона

1) Параметр инициализации \theta=(0,\theta_1,\theta_2,…,\theta_n )^T, начальное значение \theta=(0, 0, 0, …, 0 )^T

2) Получите образец X, добавьте 1 перед каждым образцом, x=(1,x_1,x_2,…,x_n )^T

3) Используйте сигмовидную функцию, чтобы предсказать выборку

4) Рассчитайте градиент в соответствии с функцией логарифмического правдоподобия g=\nabla_\theta l(\theta)

5) Рассчитайте матрицу Гессе H в соответствии с функцией логарифмического правдоподобия, H_{ij}=\frac{\partial_2 l(\theta)}{\partial\theta_i \partial\theta_j}

6) Обновить параметр \theta=\theta-H^{-1}g

Повторяйте шаги 3-6 до тех пор, пока точность результата не будет соответствовать требованиям, или итерация завершится, когда будет достигнуто определенное количество раз.

При добавлении обычных терминов

Изменить шаги 4 и 5

4) g=\nabla_\theta l(\theta)+\frac{\lambda}{m}\theta

5) Рассчитайте матрицу Гессе H и добавьте к H следующее:

\frac{\lambda}{m} \begin{pmatrix} 0 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & ... & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix}

В-четвертых, реализация кода

Примечание. Код предназначен для версии Python3.

Полный код и образцы находятся на Github,Нажмите здесь, чтобы просмотреть.

1. Градиентный спуск

#############################################
# 梯度下降法估计参数
# X 是样本特征矩阵,每一行表示一个样本
# Y 是样本 X 中对应的标签,数组类型
# alpha 表示步长
#############################################
def gradientDescent(X, Y, alpha=0.001):
    # 在矩阵 X 的第一列插入 1
    X = np.insert(X, 0, 1, 1)
    # m 是训练样本数,n-1 是样本的特征数
    m, n = X.shape
    # 初始化 theta 值
    theta = np.mat(np.zeros(n))

    # 迭代求解theta
    for i in range(2000):
        theta -= alpha * gradient(X, Y, theta)

    debug("theta:", theta)
return theta

2. Градиентный спуск (с членом регуляризации)

#############################################
# 正则化的梯度下降法估计参数
# X 是样本特征矩阵,每一行表示一个样本
# Y 是样本 X 中对应的标签,数组类型
# alpha 表示步长
#############################################
def regularizedGradientDescent(X, Y, alpha=0.001):
    # 在矩阵 X 的第一列插入 1
    X = np.insert(X, 0, 1, 1)
    # m 是训练样本数,n-1 是样本的特征数
    m, n = X.shape
    # 初始化 theta 值
    theta = np.mat(np.zeros(n))
    # 惩罚系数
    lambda_ = 0.01 / Y.size

    # 迭代求解theta
    for i in range(200000):
        theta -= alpha * gradient(X, Y, theta)
        theta[0,1:] -= lambda_ * theta[0,1:]

    debug("theta:", theta)
return theta

3. Метод Ньютона

#############################################
# 牛顿法估计参数
# X 为特征矩阵,Y 为标签,iterNum 为迭代次数
#############################################
def newtonMethod(X, Y, iterNum=10):
    # 在矩阵 X 的第一列插入 1
    X = np.insert(X, 0, 1, 1)
    # m 是训练样本数,n-1 是样本的特征数
    m, n = X.shape
    # 初始化 theta 值
    theta = np.mat(np.zeros(n))

    # 迭代求解theta
    for iterIndex in range(iterNum):
        g = gradient(X, Y, theta)
        H = hessianMatrix(X, Y, theta)
        theta -= (H.I * g.T).T
        debug("theta({}):\n{}\n".format(iterIndex + 1, theta))

return theta

4. Метод Ньютона (с регулярным членом)

#############################################
# 正则化牛顿法估计参数
# X 为特征矩阵,Y 为标签,iterNum 为迭代次数
#############################################
def regularizedNewtonMethod(X, Y, iterNum=10):
    # 在矩阵 X 的第一列插入 1
    X = np.insert(X, 0, 1, 1)
    # m 是训练样本数,n-1 是样本的特征数
    m, n = X.shape
    # 初始化 theta 值
    theta = np.mat(np.zeros(n))
    # 惩罚系数
    lambda_ = 0.01 / Y.size
    # hessian 矩阵正则项
    A = np.eye(theta.size)
    A[0,0] = 0

    # 迭代求解theta
    for iterIndex in range(iterNum):
        g = gradient(X, Y, theta) + lambda_ * theta
        H = hessianMatrix(X, Y, theta) + lambda_ * A
        theta -= (H.I * g.T).T
        debug("theta({}):\n{}\n".format(iterIndex + 1, theta))

return theta

Статьи по Теме