Логистическая регрессия - это алгоритм классификации. Логистическая регрессия состоит из логистической или сигмоидной функции для классификации классов на основе заданных данных. Чтобы узнать о Линейной регрессии, вы также можете посетить http://link.medium.com/o8drE5cyG4

Начнем процесс обучения пошагово с примера. Предположим, мы хотим обнаружить диабет независимо от того, есть ли у субъекта диабет или нет. Здесь у нас есть два класса, независимо от того, есть у субъекта диабет или нет (1 или 0).

Представление модели:

Входная переменная или характеристики (X): глюкоза, артериальное давление, инсулин, возраст и т. Д.

Выходная переменная или цель (Y): 1 или 0 (диабет - да [1] или нет диабета - нет [0]). Здесь наша целевая переменная - «Результат».

m: Количество обучающих примеров (строки)

n: количество функций (столбцы; исключая столбец Target). Здесь количество функций равно 8. [Беременность, уровень глюкозы, артериальное давление, толщина кожи, инсулин, ИМТ, функция диабета, родословная, возраст]

X (i): i-й обучающий пример, например, X1 (0) is 6 X1 (1) is 1 аналогично для y (i)

Здесь матрица X содержит функции, например, X1 = беременность, X2 = глюкоза, X3 = кровяное давление и т. Д. Здесь X имеет размерность (m, n + 1) и тета с размером (n + 1,1), где n - число Здесь включен вектор-столбец из единиц (X0), чтобы размерность X стала (m, n + 1).

Теперь здесь Θ изначально принимается равным нулю, мы хотим, чтобы значение тета было подходящим, чтобы общее значение H (Θ), то есть прогнозируемый y, имел минимальную ошибку с фактическим y.

Матрица Y представляет собой целевую переменную, то есть Y = результат из вышеуказанного набора данных.

Гипотеза или функция прогнозирования: Мы будем обозначать функцию прогнозирования как H (Θ).

Z = Θ0*X0(i) + Θ1*X1(i)

H(Θ) = g(Θ0*X0(i) + Θ1*X1(i))

H(Θ) = g(Z)

Здесь g (Z) - сигмовидная функция, которая дает значение от 0 до 1.

Если H (Θ) ≥ 0,5, то H (Θ) = 1

например, если H () = 0,7 означает, что у субъекта 70% шансов диабета, а 30% говорят, что у него нет диабета.

Если H (Θ) ‹0,5, то H (Θ) = 0

например, если H (Θ) = 0,2 означает, что у субъекта есть 20% -ные шансы на диабет, а 80% говорят, что у него нет диабета.

Вместо того, чтобы вычислять цикл, чтобы найти Z = Θ0 * X0 (i) + Θ1 * X1 (i), мы собираемся реализовать векторизацию, и следующее можно преобразовать в:

Z = X*Θ

H(Θ) = g(Z)

Изображение выше описывает преобразование матрицы из указанного выше набора данных о диабете, где X - это данные, содержащие все примеры функций, а y - цель. Здесь X0 (i) = 1.

Мы собираемся найти значения тета, используя алгоритм градиентного спуска. Перед тем, как перейти к градиентному спуску, важно знать функцию стоимости, поскольку она будет использоваться при градиентном спуске.

Функция стоимости: чтобы измерить ошибку между фактическим y и (H (Θ)) прогнозируемым y, нам нужна метрика ошибки, то есть функция стоимости J ().

J (Θ) = - (1 / m) * (y .T * log (hΘ (x (i))) + (1 - y) .T * log (1 - hΘ (x (i))))

T = транспонирование матрицы

m: Количество обучающих примеров (строки)

H (Θ): прогнозируемый y

Градиентный спуск. Итак, у нас есть гипотеза или функция прогноза, и у нас есть способ измерить, насколько хорошо она согласуется с данными. Теперь нам нужно оценить параметры Θ в функции гипотезы. Вот тут и приходит на помощь градиентный спуск.

Итак, мы собираемся измерить его по формуле, приведенной ниже:

Θ = Θ -альфа * град

альфа: скорость обучения

град: (1 / m) * ((H (Θ) -y) .T * (X)). T

Выполняя частную производную от J (Θ) по t Θ:

grad = ∂J (Θ) ∕ ∂Θ = (1 / m) * ((H (Θ) -y) .T * (X)). T

T = транспонирование матрицы

Мы будем повторять (Θ = Θ -alpha * grad) до сходимости или, можно сказать, до тех пор, пока стоимость J (Θ) не станет минимальной.

альфа или скорость обучения: альфа - это гиперпараметр, называемый скоростью обучения. Скорость обучения не должна быть слишком маленькой или слишком большой. Например, если альфа слишком велика, градиентный спуск может выходить за пределы минимума. Он может не сходиться или даже расходиться. Если альфа слишком мала, градиентный спуск может быть медленным. пробуя другое значение альфы, например [0.001,0.01,0.1,1,0.003,0.03,0.3,3], мы можем получить представление, которое было бы целесообразно выбрать.

Если мы хотим знать, работает алгоритм или нет, мы просто построим график зависимости J (Θ) от no. итераций.

Если стоимость уменьшается с итерациями, значит, наш алгоритм градиентного спуска работает нормально.

Итак, до сих пор мы видели, как работает логистическая регрессия и как она использует линейную функцию и делает активацию от 0 до 1 с помощью сигмоидной функции.

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

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

Здесь pandas используется для импорта файла csv, numpy будет использоваться для части матричной алгебры, а matplotlib будет использоваться для построения графика стоимости за итерацию.

Теперь с помощью функции pandas read_csv импортируем данные.

data = pd.read_csv("D:\\diabetes.csv")
data.head()

Здесь data.head () будет отображать первые 5 строк данных.

Здесь 9 столбцов и 768 строк, в которых столбцы от беременностей до возраста будут представлять матрицу характеристик X, а столбец результатов - Y (тот, который мы хотим предсказать).

Теперь мы собираемся разделить нашу на функции (X) и цель (Y).

X = data.drop(['Outcome'],axis=1)
X.head()

Здесь X содержит все функции, отбрасывая столбец Outcome, который является Target.

y = data['Outcome']

Теперь вставляем столбец Результат в Y.

Чтобы узнать, сколько пациентов болеют диабетом или нет, мы можем просто визуализировать это с помощью sns.countplot.

import seaborn as sns
sns.countplot(x=y)

Они показывают следующий график:

Это показывает, что согласно отчету около 500 пациентов не страдают диабетом и около 250 пациентов страдают диабетом.

Теперь мы собираемся преобразовать наши переменные X и y в матрицу. На данный момент переменные X и y относятся к типу Data-Frames, поэтому нам нужно скрыть их в матрице.

Следующее можно сделать, чтобы преобразовать Data-Frame в матрицу

X = np.matrix(X)
y = np.matrix(y).T
Output: 
X matrix-
matrix([[  6.   , 148.   ,  72.   , ...,  33.6  ,   0.627,  50.   ],
        [  1.   ,  85.   ,  66.   , ...,  26.6  ,   0.351,  31.   ],
        [  8.   , 183.   ,  64.   , ...,  23.3  ,   0.672,  32.   ],
        ...,
        [  5.   , 121.   ,  72.   , ...,  26.2  ,   0.245,  30.   ],
        [  1.   , 126.   ,  60.   , ...,  30.1  ,   0.349,  47.   ],
        [  1.   ,  93.   ,  70.   , ...,  30.4  ,   0.315,  23.   ]])
y matrix-
matrix([[1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0,0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0,0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0,0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1,0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,..........,0,1,0,0,1,0, 0, 0, 1, 0]], dtype=int64)

Теперь я собираюсь использовать нормализацию признаков для матрицы признаков. Нормализация признаков используется для улучшения градиентного спуска, поэтому время вычислений сокращается.

mean = np.mean(X,axis = 0)
std = np.std(X,axis = 0)
X = (X - mean)/std

Приведенный выше код является нормой функции для матрицы X.

Теперь мы собираемся сложить стек X0, имеющий размерность (m, 1), где m - номер. обучающего примера.

m,n = X.shape
print("Dimension of X : ",X.shape)
print("Dimension of Y : ",Y.shape)
Output:
Dimension of X : (768,8)
Dimension of Y: (768,1)
Here m is 768 and n features 8

Теперь добавляем столбец X0 к X

X0 = np.ones((m,1))
X = np.hstack((X0,X))
Output:
X matrix
matrix([[ 1.        ,  0.63994726,  0.84832379, ...,  0.20401277,
          0.46849198,  1.4259954 ],
        [ 1.        , -0.84488505, -1.12339636, ..., -0.68442195,
         -0.36506078, -0.19067191],
        [ 1.        ,  1.23388019,  1.94372388, ..., -1.10325546,
          0.60439732, -0.10558415],
        ...,
        [ 1.        ,  0.3429808 ,  0.00330087, ..., -0.73518964,
         -0.68519336, -0.27575966],
        [ 1.        , -0.84488505,  0.1597866 , ..., -0.24020459,
         -0.37110101,  1.17073215],
        [ 1.        , -0.84488505, -0.8730192 , ..., -0.20212881,
         -0.47378505, -0.87137393]])

Now the X shape will (m,n+1) i.e(768,9)

Теперь давайте создадим матрицу Θ, т.е. формы (n + 1,1).

theta=np.zeros((n+1,1))

Теперь мы собираемся создать сигмовидную функцию, т.е.

def sigmoid(Z):
    S = 1/(1 + np.exp(-Z))
    return S

Теперь создаем нашу функцию прогнозирования, т.е. H (Θ) = g (Z)

def prediction(X,theta):
    Z = X * theta
    htheta = sigmoid(Z)
    return htheta

Теперь создаем функцию стоимости для измерения ошибки.

J (Θ) = - (1 / m) * (y .T * log (hΘ (x (i))) + (1 - y) .T * log (1 - hΘ (x (i))))

def cost(pred,y):
    J = (-1/m)*(y.T*np.log(pred) + (1 - y).T * np.log( 1 - pred ))   
    return J

Теперь создаем функцию градиента для вычисления Θ.

град = (1 / m) * ((H (Θ) -y) .T * (X)). T

def grad(X,prediction,y):
    d_theta = (1/m) * (X.T * (prediction - y))
    return d_theta

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

def LogisticRegression(X,y,theta,alpha,epoch):
    
    j_history=[]
    
    for i in range(epoch):
        
        pred = prediction(X,theta)
        J = cost(pred,y)
        g = grad(X,pred,y)
        theta = theta - alpha*d_theta
        j_history = np.append(j_history,J)
        
        print("Epoch : ",i," ","cost : ",J)
    
    x = np.linspace(0,epoch,epoch)
    plt.ylabel("cost function")
    plt.plot(x,j_history,color='r')
    plt.xlabel("No. of iterations")
    plt.title("Decreasing of cost function")
    
    return theta,pred

Как вы можете видеть выше, j_history используется для экономии затрат на итерацию, чтобы визуализировать соотношение затрат и итераций, независимо от того, уменьшается она или нет.

theta,pred = LogisticRegression(X,y,theta,alpha=2,epoch=30)
Output :
Epoch :  0   cost :  [[0.69314718]]
Epoch :  1   cost :  [[0.53342096]]
Epoch :  2   cost :  [[0.50414229]]
Epoch :  3   cost :  [[0.49056751]]
Epoch :  4   cost :  [[0.48328456]]
Epoch :  5   cost :  [[0.47902958]]
Epoch :  6   cost :  [[0.47639795]]
Epoch :  7   cost :  [[0.47470381]]
Epoch :  8   cost :  [[0.47358081]]
Epoch :  9   cost :  [[0.47281983]]
Epoch :  10   cost :  [[0.47229528]]
Epoch :  11   cost :  [[0.47192879]]
Epoch :  12   cost :  [[0.47166992]]
Epoch :  13   cost :  [[0.47148541]]
Epoch :  14   cost :  [[0.47135292]]
Epoch :  15   cost :  [[0.47125718]]
Epoch :  16   cost :  [[0.47118761]]
Epoch :  17   cost :  [[0.47113683]]
Epoch :  18   cost :  [[0.47109961]]
Epoch :  19   cost :  [[0.47107223]]
Epoch :  20   cost :  [[0.47105202]]
Epoch :  21   cost :  [[0.47103706]]
Epoch :  22   cost :  [[0.47102597]]
Epoch :  23   cost :  [[0.47101772]]
Epoch :  24   cost :  [[0.47101156]]
Epoch :  25   cost :  [[0.47100697]]
Epoch :  26   cost :  [[0.47100353]]
Epoch :  27   cost :  [[0.47100096]]
Epoch :  28   cost :  [[0.47099902]]
Epoch :  29   cost :  [[0.47099757]]

Вышеупомянутый блок вызовет функцию LogisticRegression, чтобы подобрать данные (X, y) для обучения и получить значения тета и прогноза.

Теперь займемся поиском точности модели.

predict = prediction(X,theta)
print(predict)
for i in range(len(predict)):
    if predict[i]>=0.50:
        predict[i]=1
    else:
        predict[i]=0
k = np.double(predict == y)
acc = np.mean(k)*100
print(acc)
Output:
78.25520833333334

Мы также можем использовать фреймворк программирования машинного обучения «sklearn».

Как мы видим, точность нашей модели составляет 78,255%, а у моделей sklearn - 78,125%, что близко друг к другу.

Позвольте мне объяснить вам, как работает среда программирования. Сначала импортируйте LogisticRegression из линейной модели sklearn.

Создать объект своего класса

clf = LogisticRegression (max_iter = 1000, random_state = 0) .fit (X, y) тренирует данные, как мы создали функцию LogisticRegression (X, y, theta, alpha = 3, epoch = 30).

clf.predict () используется для прогнозов

clf.score (X, y) дает точность между фактическим y и прогнозируемым y.

Для получения дополнительной информации по его использованию вы можете посетить https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LogisticRegression.html

Теперь мы можем завершить его простой схемой процесса, как показано ниже: