Алгоритм логистической регрессии для машинного обучения

машинное обучение

Алгоритм логистической регрессии

В этой статье представлен алгоритм логистической регрессии в машинном обучении, который мы используем для классификации данных. Алгоритм логистической регрессии также является алгоритмом обучения с учителем, который должен обучаться через пространство выборки и подходит для числовых и номинальных данных.Например, нам нужно судить о данных в соответствии с размером собственного значения (числового) ввода данные Не какая-то классификация.

1. Пример данных

В нашем случае у нас есть некоторые примеры данных, подобные этому:

  • Демонстрационные данные имеют 3 собственных значения: X0X0, X1X1, X2X2.
  • Мы оцениваем, соответствуют ли данные требованиям, через X1X1 и X2X2 в этих трех собственных значениях, то есть 1, если данные соответствуют требованиям, и 0, если они не соответствуют требованиям.
  • Данные выборки классифицируются и сохраняются в массиве

Мы пишем следующие функции в файле logRegres.py для подготовки данных и распечатываем данные для наблюдения:

#coding=utf-8
from numpy import *
def loadDataSet():
    dataMat = []; labelMat = []
    fr = open('testSet.txt')
    for line in fr.readlines():
        lineArr = line.strip().split()
        dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])
        labelMat.append(int(lineArr[2]))
    return dataMat,labelMat
if __name__=='__main__':
    dataMat,labelMat=loadDataSet()
    print 'dataMat:\n',dataMat

Давайте посмотрим на этот образец данных:

dataMat:
[[1.0, -0.017612, 14.053064], [1.0, -1.395634, 4.662541], [1.0, -0.752157, 6.53862], [1.0, -1.322371, 7.152853], [1.0, 0.423363, 11.054677], [1.0, 0.406704, 7.067335], [1.0, 0.667394, 12.741452], [1.0, -2.46015, 6.866805], [1.0, 0.569411, 9.548755], [1.0, -0.026632, 10.427743], [1.0, 0.850433, 6.920334], [1.0, 1.347183, 13.1755], [1.0, 1.176813, 3.16702], [1.0, -1.781871, 9.097953], [1.0, -0.566606, 5.749003], [1.0, 0.931635, 1.589505], [1.0, -0.024205, 6.151823], [1.0, -0.036453, 2.690988], [1.0, -0.196949, 0.444165], [1.0, 1.014459, 5.754399], [1.0, 1.985298, 3.230619], [1.0, -1.693453, -0.55754], [1.0, -0.576525, 11.778922], [1.0, -0.346811, -1.67873], [1.0, -2.124484, 2.672471], [1.0, 1.217916, 9.597015], [1.0, -0.733928, 9.098687], [1.0, -3.642001, -1.618087], [1.0, 0.315985, 3.523953], [1.0, 1.416614, 9.619232], [1.0, -0.386323, 3.989286], [1.0, 0.556921, 8.294984], [1.0, 1.224863, 11.58736], [1.0, -1.347803, -2.406051], [1.0, 1.196604, 4.951851], [1.0, 0.275221, 9.543647], [1.0, 0.470575, 9.332488], [1.0, -1.889567, 9.542662], [1.0, -1.527893, 12.150579], [1.0, -1.185247, 11.309318], [1.0, -0.445678, 3.297303], [1.0, 1.042222, 6.105155], [1.0, -0.618787, 10.320986], [1.0, 1.152083, 0.548467], [1.0, 0.828534, 2.676045], [1.0, -1.237728, 10.549033], [1.0, -0.683565, -2.166125], [1.0, 0.229456, 5.921938], [1.0, -0.959885, 11.555336], [1.0, 0.492911, 10.993324], [1.0, 0.184992, 8.721488], [1.0, -0.355715, 10.325976], [1.0, -0.397822, 8.058397], [1.0, 0.824839, 13.730343], [1.0, 1.507278, 5.027866], [1.0, 0.099671, 6.835839], [1.0, -0.344008, 10.717485], [1.0, 1.785928, 7.718645], [1.0, -0.918801, 11.560217], [1.0, -0.364009, 4.7473], [1.0, -0.841722, 4.119083], [1.0, 0.490426, 1.960539], [1.0, -0.007194, 9.075792], [1.0, 0.356107, 12.447863], [1.0, 0.342578, 12.281162], [1.0, -0.810823, -1.466018], [1.0, 2.530777, 6.476801], [1.0, 1.296683, 11.607559], [1.0, 0.475487, 12.040035], [1.0, -0.783277, 11.009725], [1.0, 0.074798, 11.02365], [1.0, -1.337472, 0.468339], [1.0, -0.102781, 13.763651], [1.0, -0.147324, 2.874846], [1.0, 0.518389, 9.887035], [1.0, 1.015399, 7.571882], [1.0, -1.658086, -0.027255], [1.0, 1.319944, 2.171228], [1.0, 2.056216, 5.019981], [1.0, -0.851633, 4.375691], [1.0, -1.510047, 6.061992], [1.0, -1.076637, -3.181888], [1.0, 1.821096, 10.28399], [1.0, 3.01015, 8.401766], [1.0, -1.099458, 1.688274], [1.0, -0.834872, -1.733869], [1.0, -0.846637, 3.849075], [1.0, 1.400102, 12.628781], [1.0, 1.752842, 5.468166], [1.0, 0.078557, 0.059736], [1.0, 0.089392, -0.7153], [1.0, 1.825662, 12.693808], [1.0, 0.197445, 9.744638], [1.0, 0.126117, 0.922311], [1.0, -0.679797, 1.22053], [1.0, 0.677983, 2.556666], [1.0, 0.761349, 10.693862], [1.0, -2.168791, 0.143632], [1.0, 1.38861, 9.341997], [1.0, 0.317029, 14.739025]]
labelMat:
[0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0]

образецdataMatПервый столбец , то есть наши собственные значения X0X0 все равны 1. Нам нужно обратить внимание, чтобы понять эту проблему при расчете параметров регрессии. Всего имеется 100 единиц выборочных данных, и соответствующие результаты классификации также составляют 100 единиц.

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

2. Сигмовидная функция

Чтобы решить проблемы, о которых мы упоминали в предыдущем разделе, давайте сначала представим сигмовидную функцию:

Эта функция имеет следующие характеристики:

  • Когда z=0z=0, значение равно 0,50,5.
  • Поскольку zz продолжает увеличиваться, значение будет приближаться к 1
  • Поскольку zz продолжает уменьшаться, значение будет приближаться к 0

Посмотрим на график функции:

Если мы подставим в функцию значения трех собственных значений X0X0, X1X1 и X2X2 выборочного пространства, мы сможем вычислить результат. Тогда этот результат будет близок к нашему результату классификации (число от 0 до 1). Если результат близок к 0, то мы рассматриваем классификацию как 0, если результат близок к 1, мы рассматриваем классификацию как 1.

Каким образом он подставляется в функцию? На самом деле можно сделать простое сложение, потому что, когда zz продолжает увеличиваться или уменьшаться, значение функции приближается к 1 или 0 соответственно. Делаем z=x0+x1+x2z=x0+x1+x2

Но реальная ситуация такова, что наши результаты расчета и фактические значения классификации будут иметь ошибки, а то и вовсе неверны. Чтобы исправить эту проблему, мы определяем коэффициент регрессии w0w0, w1w1 и w2w2 для трех собственных значений X0X0, X1X1 и X2X2 выборочного пространства, чтобы уменьшить эту ошибку. даже если z=w0x0+w1x1+w2x2

На самом деле нетрудно представить, что значение этого набора коэффициентов регрессии ww определяет точность и даже правильность результатов наших расчетов. То есть этот набор значений ww отражает правила классификации пространства выборки.
Затем, когда мы вводим данные, отличные от набора выборок, с правильным коэффициентом регрессии ww, мы можем получить результаты классификации, которые ближе к правилам классификации пространства выборки.
Вопрос снова в том, как мы можем получить такой набор коэффициентов регрессии ww?

3. Метод градиентного восхождения

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

Среди них αα — размер шага, а Δσ(w)Δσ(w) — градиент функции σ(w)σ(w). Для получения градиента см.здесь. Математические способности автора ограничены и не будут объяснены.
Наконец, мы можем получить формулу для расчета градиента:

Тогда формула итерации выглядит следующим образом:

Описание формулы:

  • wk+1wk+1 — результат коэффициента регрессии элемента функции XX в этой итерации.
  • wkwk — результат коэффициента регрессии элемента функции XX предыдущей итерации.
  • αα - размер шага каждой итерации, движущейся в направлении градиента
  • xixi — i-й элемент в элементе функции XX.
  • yiyi — результат выборки классификации i-й записи в выборке.
  • σ(xi,wk)σ(xi,wk) — i-я запись в выборке, результат классификации вычисляется с помощью сигмовидной функции и wkwk как коэффициента регрессии
  • [yi−σ(xi,wk)][yi−σ(xi,wk)] — значение результата классификации, соответствующее i-й записи выборки, и значение ошибки значения результата классификации, вычисленное сигмовидной функцией с использованием wkwk как коэффициент регрессии.

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

def gradAscent(dataMatIn, classLabels):
    dataMatrix = mat(dataMatIn)             #100行3列
    #print dataMatrix
    labelMat = mat(classLabels).transpose() #100行1列
    #print 'labelMat:\n',labelMat
    print 'labelMat 的形状:rowNum=',shape(labelMat)[0],'colNum=',shape(labelMat)[1]
    rowNum,colNum = shape(dataMatrix)
    alpha = 0.001
    maxCycles = 500
    weights = ones((colNum,1))  #3行1列
    #print shape(dataMatrix)
    #print shape(weights)
    #print shape(labelMat)
    for k in range(maxCycles):              #heavy on matrix operations
        h = sigmoid(dataMatrix*weights)     #100行1列
        #print h
        error = (labelMat - h)              #vector subtraction
        weights = weights + alpha * dataMatrix.transpose()* error #3行1列
    return weights
if __name__=='__main__':
    dataMat,labelMat=loadDataSet()
    #weights=gradAscent(dataMat,labelMat)
    #print 'dataMat:\n',dataMat
    #print 'labelMat:\n',labelMat
    print weights

распечатать результат:

回归系数:
[[ 4.12414349]
 [ 0.48007329]
 [-0.6168482 ]]

Чтобы проверить точность наших рассчитанных ретроспективных коэффициентов, мы наблюдаем диаграмму рассеяния выборочного пространства и подобранную кривую коэффициентов регрессии. Мы используем z(x1,x2)=w0+w1x1+w2x2 в качестве нашей подгоночной функции и рисуем ее подгоночную кривую в системе координат. Используя значения X1X1 и X2X2 в пространстве выборки в качестве абсцисс и ординат, нарисуйте разброс в пространстве выборки. код показывает, как показано ниже:

def plotBestFit(weights):
    import matplotlib.pyplot as plt
    dataMat,labelMat=loadDataSet()
    dataArr = array(dataMat)
    n = shape(dataArr)[0] 
    xcord1 = []; ycord1 = []
    xcord2 = []; ycord2 = []
    for i in range(n):
        if int(labelMat[i])== 1:
            xcord1.append(dataArr[i,1]); ycord1.append(dataArr[i,2])
        else:
            xcord2.append(dataArr[i,1]); ycord2.append(dataArr[i,2])
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(xcord1, ycord1, s=30, c='red', marker='s')
    ax.scatter(xcord2, ycord2, s=30, c='green')
    x = arange(-3.0, 3.0, 0.1)
    y = (-weights[0]-weights[1]*x)/weights[2]
    y = y.transpose()
    ax.plot(x, y)
    plt.xlabel('X1'); plt.ylabel('X2');
    plt.show()
if __name__=='__main__':
    dataMat,labelMat=loadDataSet()
    weights=gradAscent(dataMat,labelMat)
    print '回归系数:\n',weights
    plotBestFit(weights)

После запуска получаем следующую картину:

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

Далее давайте реализуем классификатор и протестируем этот классификатор:

def classify0(targetData,weights):
    v = sigmoid(targetData*weights)
    if v>0.5:
        return 1.0
    else :
        return 0
def testClassify0():
    dataMat,labelMat=loadDataSet()
    examPercent=0.7
    row,col=shape(dataMat)
    exam=[]
    exam_label=[]
    test=[]
    test_label=[]
    for i in range(row):
        if i < row*examPercent:
            exam.append(dataMat[i])
            exam_label.append(labelMat[i])
        else:
            test.append(dataMat[i])
            test_label.append(labelMat[i])
    weights=gradAscent(exam,exam_label)
    errCnt=0
    trow,tcol=shape(test)
    for i in range(trow):
        v=int(classify0(test[i],weights))
        if v != int(test_label[i]):
            errCnt += 1
            print '计算值:',v,' 原值',test_label[i]
    print '错误率:',errCnt/trow
if __name__=='__main__':
    #dataMat,labelMat=loadDataSet()
    #weights=gradAscent(dataMat,labelMat)
    ##print 'dataMat:\n',dataMat
    ##print 'labelMat:\n',labelMat
    #print '回归系数:\n',weights
    #plotBestFit(weights)
    testClassify0()

Реализация классификатора проста. Мы используем 70 фрагментов данных из предыдущей выборки данных в качестве выборки данных для нашего теста и вычисляем коэффициент регрессии. Затем используйте классификатор для классификации оставшихся 30 записей, а затем сравните результаты с выборочными данными. Наконец, распечатайте частоту ошибок. Как мы видим, процент ошибок равен 0, что почти идеально! Мы можем изменить пропорцию тестовой выборки в исходном пространстве выборки и протестировать ее несколько раз. Итак, вывод - точность нашего алгоритма неплохая!

Итак, здесь проблема решена? Кажется, чего-то не хватает. Давайте подробнее рассмотрим наш метод расчета коэффициентов регрессии, Нетрудно обнаружить, что в этом процессе мы выполняем матричное умножение с матрицей, составленной из выборочных данных. То есть для расчета коэффициентов регрессии мы проходим по всей выборке данных.

Наша проблема возникает снова.Выборочных данных в нашем примере всего 100. Если мы обработаем тысячи выборочных данных, вычислительная сложность нашей функции для расчета коэффициентов регрессии резко возрастет. Давайте посмотрим, как оптимизировать этот алгоритм.

В-четвертых, оптимизируйте алгоритм градиентного подъема - метод стохастического градиентного подъема.

Разбираемся с формулой итеративного расчета коэффициентов регрессии


и после программы, которую мы реализовали. Усовершенствуем метод расчета коэффициентов регрессии следующим образом:

def stocGradAscent0(dataMatrix, classLabels):
    m,n = shape(dataMatrix)
    alpha = 0.01
    weights = ones((n,1))   #initialize to all ones
    for i in range(m):
        h = sigmoid(sum(dataMatrix[i]*weights))
        error = classLabels[i] - h
        weights = weights + alpha * error * mat(dataMatrix[i]).transpose()
    return weights

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

Нетрудно заметить, что отличие от предыдущего алгоритма все еще относительно велико. Причина в том, что предыдущий алгоритм рассчитывался за 500 итераций, последний только за 100 итераций. Тогда проблема, которую следует здесь объяснить, заключается в том, что коэффициент регрессии имеет тенденцию сходиться с увеличением числа итераций, а процесс сходимости флуктуирует. Грубо говоря, чем больше итераций, тем ближе значение, которое мы хотим, но поскольку выборочные данные нелинейны, в этом процессе будут определенные ошибки. Чтобы узнать о взаимосвязи между конкретным коэффициентом регрессии и количеством итераций, вы можете обратиться к некоторым учебникам, например к описанию в «Практике машинного обучения», которое здесь подробно не будет представлено.
Здесь мы только представляем, как улучшить наш алгоритм, чтобы наш алгоритм мог быстро сходиться и уменьшать колебания. Методы, как показано ниже:

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

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

def stocGradAscent1(dataMatrix, classLabels, numIter=150):
    m,n = shape(dataMatrix)
    weights = ones((n,1))   #initialize to all ones
    for j in range(numIter):
        dataIndex = range(m)
        for i in range(m):
            alpha = 4/(1.0+j+i)+0.0001    #apha decreases with iteration, does not 
            randIndex = int(random.uniform(0,len(dataIndex)))#go to 0 because of the constant
            h = sigmoid(sum(dataMatrix[randIndex]*weights))
            error = classLabels[randIndex] - h
            weights = weights + alpha * error * mat(dataMatrix[randIndex]).transpose()
            del(dataIndex[randIndex])
    return weights
if __name__=='__main__':
    dataMat,labelMat=loadDataSet()
    #weights=stocGradAscent0(dataMat,labelMat)
    weights=stocGradAscent1(dataMat,labelMat)
    #weights=gradAscent(dataMat,labelMat)
    #print 'dataMat:\n',dataMat
    #print 'labelMat:\n',labelMat
    #print '回归系数:\n',weights
    plotBestFit(weights)
    #testClassify0()

По умолчанию используется 150 итераций выборочных диаграмм рассеяния и построенных кривых:

Нетрудно заметить, что точность очень близка к первому алгоритму!

V. Резюме

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

1 лайксобиратьКомментарий