English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
本文介绍机器学习中的Logistic回归算法,我们使用这个算法来给数据进行分类。Logistic回归算法同样是需要通过样本空间学习的监督学习算法,并且适用于数值型和标称型数据,例如,我们需要根据输入数据的特征值(数值型)的大小来判断数据是某种分类或者不是某种分类。
一、样本数据
在我们的例子中,我们有这样一些样本数据:
样本数据有3个特征值:X0X0,X1X1,X2X2
我们通过这3个特征值中的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, то есть наших признаков X0, все значения равны 1. Этот момент нужно учитывать при вычислении параметров регрессии. В всего样本ах 100 штук, и для каждого из них есть результат классификации 100 штук.
Таким образом, наша текущая проблема заключается в том:
Нам нужно найти связь между значением признака в пространстве样本ов и результатом классификации. Мы должны спроектировать функцию или функциональность, которая, после ввода набора значений признаков, автоматически классифицирует вводимые данные, результатом которой будет либо 1, либо 0.
II. Функция Sigmoid
Чтобы решить проблему, упомянутую нами в предыдущем разделе,我们先介绍一下Sigmoid функцию:
Эта функция имеет следующие характеристики:
Когда z=0, значение равно 0,5
Когда zz неуклонно увеличивается, значение приближается к 1
Когда z постоянно уменьшается, значение приближается к 0
Давайте посмотрим на график функции:
Если мы введем значения трёх характеристических значений X0, X1 и X2 области образцов в функцию и вычислим результат, то этот результат будет близок к нашему результату классификации (число между 0 и 1). Если результат близок к 0, то мы считаем классификацию 0, если результат близок к 1, то мы считаем классификацию 1.
Каким образом мы можем ввести это в функцию? На самом деле, это очень просто, просто сложить их, потому что, когда z увеличивается или уменьшается, значение функции соответственно приближается к 1 или 0. Мы делаем z = x0 + x1 + x2
Но на практике наши вычисленные результаты и фактические значения классификации могут иметь ошибки, даже completamente неправильные. Чтобы исправить эту проблему, мы определяем регрессионные коэффициенты w0, w1 и w2 для трёх характеристических значений X0, X1 и X2 области образцов, чтобы уменьшить эти ошибки. Даже если z = w0x0 + w1x1 + w2x2
На самом деле, не трудно представить, что значения этого набора w определяют точность и даже правильность наших вычисленных результатов. То есть, это значения w отражают правила классификации области образцов.
Таким образом, вводя данные образцов вместе с правильными значениями w, мы можем получить результаты классификации, которые близки к правилам классификации области образцов.
Но возникает вопрос: как мы можем получить такое значение w, которое является регрессионным коэффициентом?
Третий раздел: метод градиентного подъема
Метод градиентного подъема заключается в постоянном итерационном вычислении значений параметров в направлении градиента функции, чтобы найти наибольшее значение параметра. Итерационная формула такая:
其中, α — это шаг, Δσ(w) — это градиент функции σ(w)σ(w). О выводе градиента см.Здесь:. Математические способности автора ограничены, поэтому пояснений не будет.
В конце мы можем получить формулу вычисления градиента:
Итак, итерационная формула такая:
Объяснение формулы:
wk+1 — это результат регрессионного коэффициента для XX характеристических элементов в текущем итерационном шаге.
wk — это результат регрессионного коэффициента для XX характеристических элементов в предыдущем итерационном шаге.
α — это шаг, на который мы движемся в направлении градиента в каждом итерационном шаге.
xi — это i-й элемент из XX характеристических элементов.
yi — это результат классификации образца для i-го образца.
σ(xi,wk)σ(xi,wk) — это значение классификационного результата для i-го образца, вычисленное с использованием функции sigmoid и wkwk в качестве регрессионного коэффициента.
[yi−σ(xi,wk)][yi−σ(xi,wk)] — это значение классификационного результата для i-го образца, которое соответствует ошибке между значением классификационного результата, вычисленного с использованием функции sigmoid с 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): #тяжело для операций с матрицами h = sigmoid(dataMatrix*weights) #100 строк 1 столбец #print h error = (labelMat - h) #векторное вычитание 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 ]
Чтобы проверить точность вычисленных нами обратных коэффициентов, посмотрим на график точек вample пространства и кривую соответствия коэффициентов регрессии. Давайте возьмем функцию соответствия z(x1,x2)=w0+w1x1+w2x2 в качестве нашей функции соответствия и нарисуем ее кривую соответствия на координатной плоскости. Используя значения X1X1 и X2X2 вample пространства в качестве абсциссы и ординаты, нарисуем точки sample пространства. Код следующий:
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 итераций. Таким образом, нужно отметить, что коэффициенты регрессии стремятся к сжатию с увеличением числа итераций, и процесс сжатия имеет колебания. Другими словами, чем больше количество итераций, тем ближе мы приближаемся к желаемому значению, но из-за нелинейности данных образца этот процесс также имеет определенную ошибку. Конкретные коэффициенты регрессии и их зависимость от числа итераций можно найти в некоторых учебниках, например, в описании в 'Practice of Machine Learning', здесь не будем подробно介绍.
мы рассмотрим, как улучшить наш алгоритм, чтобы он мог быстро收敛 и уменьшить колебания. Метод таков:
в каждой итерации случайным образом выбирается точка образца для вычисления вектора регрессии
длина шага итерации с увеличением числа итераций постоянно уменьшается, но永远 не равна 0
улучшение кода и вывод графика соответствия и.scatter diagrams:
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 итераций scatter plot и график соответствия:
Не трудно看出, что точность очень接近第一个 алгоритм!
V. Заключение
Алгоритм логистической регрессии в основном использует функцию Sigmoid для классификации данных, точность классификации зависит от коэффициентов регрессии, вычисленных из образца пространства. Мы используем метод градиентного подъема для вычисления коэффициентов регрессии и используем метод случайного градиентного подъема для улучшения производительности алгоритма.
Вот полный контент статьи о логистической регрессии алгоритма машинного обучения на языке Python, который, hopefully, поможет вам. Те, кто интересуется, могут продолжить читать другие статьи по Python иАлгоритмыСвязанные темы, если есть недостатки, пожалуйста, оставьте комментарий. Спасибо друзьям за поддержку сайта!
Заявление: контент этой статьи взят из Интернета, авторские права принадлежат соответствующему автору. Контент предоставлен пользователями Интернета, сайт не имеет права собственности, не был обработан вручную и не несет ответственности за связанные с этим юридические вопросы. Если вы обнаружите подозрительный контент, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (при отправке письма замените # на @) для сообщения о нарушении авторских прав,并提供 соответствующие доказательства. Если информация подтвердится, сайт немедленно удалит спорный контент.