迴歸:若有一些數據點,用一條直線對這些點進行擬合的過程。
訓練分類器時的做法,尋找最佳擬合參數,使用最優化算法。
準備數據,要求數據類型爲數值型;訓練算法,尋找最佳的分類迴歸係數。使用算法,輸入數據,轉化爲結構化數值,基於迴歸係數,對這些數值進行迴歸計算,判定分類。
基於Logistic迴歸和Sigmoid函數的分類:
計算代價不高,但容易欠擬合,分類精度不高。
Sigmoid函數,看起來很像一個階躍函數,隨着x增大,會逼近於1。
Logistic迴歸分類器的原理:每個特徵上都乘以一個迴歸係數,然後把所有結果相加,代入Sigmoid函數,進而得到0~1之間的數值。
梯度上升法:用來求函數的最大值
f(x,y)的梯度:;梯度上升算法的迭代公式:,α爲步長。
對某數據集,使用梯度上升法,找到最佳迴歸係數:
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
def sigmoid(inX):
return 1.0 / (1 + exp(-inX))
def gradAscent(dataMatIn, classLabels):
dataMatrix = mat(dataMatIn) # 100行數據,每行有兩個特徵X1和X2
labelMat = mat(classLabels).transpose() # 轉化爲100x1的列向量
m, n = shape(dataMatrix) # 100x3
alpha = 0.001 # 目標移動的步長
maxCycles = 500 # 迭代次數
weights = ones((n, 1)) # 3x1
for k in range(maxCycles):
h = sigmoid(dataMatrix * weights) # h是一個列向量,100x1
error = (labelMat - h) # 100x1
weights = weights + alpha * dataMatrix.transpose() * error # 3x1
return weights
分析數據:畫出決策邊界:
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]
ax.plot(x, y)
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()
這裏設置sigmoid函數的x爲0,因此設定 ,然後解出兩個特徵X2和X1的關係式,此處X0=1。
訓練算法:隨機梯度上升:
上述算法,每次更新迴歸係數,都需要遍歷整個數據集,就會使得計算複雜度過高。
隨機梯度上升算法:一次僅用,一個樣本點來更新迴歸係數。因此可在新樣本到來時,對分類器進行增量式更新(在線學習)。
一個判斷優化算法優劣的可靠方法是:看它是否收斂,也就是說參數是否達到了穩定值。
def stocGradAscent1(dataMatrix, classLabels, numIter=150):
m, n = shape(dataMatrix) # 100x3
weights = ones(n) # 3
for j in range(numIter):
dataIndex = range(m)
for i in range(m):
# 每次迭代都會調整,0.0001防止α爲0
# 若處理的問題是動態變化,則適當加大上述常數項,確保新的值,獲得更大的迴歸係數
alpha = 4 / (1.0 + j + i) + 0.0001
# 當j<<max(i)時,alpha就不是嚴格下降的,避免參數嚴格下降,見於模擬退火算法
randIndex = int(random.uniform(0, len(dataIndex)))
# 隨機選取樣本來更新迴歸係數
h = sigmoid(sum(dataMatrix[randIndex] * weights))
error = classLabels[randIndex] - h
weights = weights + alpha * error * dataMatrix[randIndex]
# 從列表中刪除該值
del (dataIndex[randIndex])
return weights
ps:係數沒有出現週期性波動,歸功於樣本隨機選擇機制。僅遍歷20次左右數據集,係數即可收斂。