note:
- 一次只训练一个数据 (Online Learning)
- Online Learning: 能够根据线上反馈数据,实时快速地进行模型调整,使得模型及时反映线上的变化,提高线上预测的准确率
- 对应的是batch learning: 是一种离线的学习方法,一次性将batch大小的批量数据输入到学习算法中。
- 只有当数据被错误分类时,才会对该数据进行学习 (Error-driven learning)
- 对数据集训练循环多次,直到收敛(收敛指没有数据再被错误分类,weight 值 和 bias 值都不会再发生变化)
- 每个训练循环(iteration)前,都要打乱数据的顺序(shuffle)
- 线性可分(linearly separable),如果数据集里的数据可以被一条直线(hyperplane)正确的分成两类,我们就说这个数据集是线性可分的。否则,数据集线性不可分(nonlinearly separable)
- 分类线(hyperplane)其实并不是唯一的
- 最终训练出的weight 受最后一个数据的影响特别大,所以会采用一个升级版算法“averaged preception algorithm),它将训练过程中的weight和bias求平均值,作为最终的weight。 或者 (每个iteration都收敛的情况下)平均每个iteration的算出的weight和bias,当然每个iteration学习之前,都要重新打乱(shuffle)数据。
伪代码(pseudo code)
- a : activation
- y: 标签值(label), 1 或 -1
- 当 y * a <= 0 时,说明,预测值与标签值相背,分类错误,此时需要对该数据进行学习
学习时,更新weight 和 bias - 对数据集训练循环多次,直到收敛(收敛指没有数据再被错误分类,weight 值 和 bias 值都不会再发生变化)
- learn:
Hyperplane
不是weight 向量那条线分类,是w1x1 + w2 * x2 + … + wnxn 这条线作为hyperplane分类,weight 向量和hyperplane 是垂直的。
code
代码是我coursework的代码,我还没来得及标准化这个代码
但是可以看出大概意思,我有空再整理啦
有小伙伴要我数据集和coursework题目的,可以留言给我
from google.colab import files
import io
import numpy as np
import pandas as pd
class Preprocess(object):
#extract data base on class labels and pre-process data
def filtAndShuf(self, allData, filterclass):
#delet the data with the last class label
delClassIndex = np.where(allData[:,4]==filterclass[-1])
data = np.delete(allData, delClassIndex, axis=0)
#Replaces the class name of the string in the first column of the parameters with the numeric 1
data[data==filterclass[0]] = 1
#Replaces the class name of the string in the rest column(s) of the parameters with the numeric -1
data[:,4][data[:,4]!=1] = -1
#shuffle the data, let them order randomly
np.random.shuffle(data)
#split the data into two: the feature data and the label data
x,y = np.split(data,[4],axis=1)
#inset a column to x with value equal to 1 corresponding to the bias column as the w0
x=np.insert(x, 0, values=np.ones(x.shape[0]), axis=1)
y = y[:,0]
return(x,y)
class Perceptron(object):
def updateWeight(self, x, y, w, λ, eta):
incorCount = 0
for i in range(x.shape[0]):
#calculate the action value
a = np.dot(w, x[i,:])
#detect if the instance is incorrectly classified
if a*y[i] <= 0:
#update the weight, eta is learning rate, the λ is the regularisation coefficient
w = w + eta * y[i] * x[i,:] - eta * λ * w
#count the number of misclassified instance
incorCount += 1
#calculate the accuracy
accuracy = 1- incorCount / x.shape[0]
return(w, incorCount, accuracy)
if __name__ == '__main__':
################################################################################
### parameters preparation ###
################################################################################
preprocess = Preprocess()
perceptron = Perceptron()
#import data
uploaded = files.upload()
trainData = pd.read_csv(io.BytesIO(uploaded['train.data']),header=None)
testData = pd.read_csv(io.BytesIO(uploaded['test.data']),header=None)
trainData = np.array(trainData)
testData = np.array(testData)
#names for the three classifiers, which can makes print convenient
classifierName = np.array([['1-vs-2', '1-vs-3', '2-vs-3'],
['1-vs-rest','2-vs-rest','3-vs-rest']])
#indicate how to process the three binary classfiers, the last class(column) will be deleted
#the first two columns will be labeled as 1 and -1 respectively
binaryClass = np.array([['class-1','class-2','class-3'],
['class-1','class-3','class-2'],
['class-2','class-3','class-1']])
#indicate how to process the three multi-classifiers, the last class(column) will be deleted
#the first class(column) will be labeled as 1, the middle two classes(columns) will be labeled as -1
multiClass = np.array([['class-1', 'class-2', 'class-3', 'None'], ['class-2', 'class-1', 'class-3', 'None'],
['class-3', 'class-1', 'class-2', 'None']])
dataName = np.array(['trainData', 'testData'])
data = np.array([trainData, testData])
################################################################################
### Answers to Question 3 ###
################################################################################
print('\nQuestion 3, Binary classifier training')
finalWeight = np.zeros([3, 5], dtype=float)
for k in range(3): # 3 classifiers
#initial the weights for each iteration
weight=np.zeros((20,5),dtype=float)
for i in range(20): # 20 iteration
#extract and pre-process the data for the binary classifier training
x, y = preprocess.filtAndShuf(trainData, binaryClass[k,:])
#record the weight after each iteration training
weight[i,:], incorCount, accuracy = perceptron.updateWeight(x, y, weight[i,:], 0, 1)
#the final weights for the three
finalWeight[k,:] = np.sum(weight, axis=0) / weight.shape[0]
print(classifierName[0,k], 'weight =', np.around(finalWeight[k,[1,2,3,4]], decimals=2),\
' bias =', np.around(finalWeight[k,0], decimals=2))
################################################################################
### Answers to Question 4 ###
################################################################################
print('\nQuestion 4, Binary classification accuracy')
for k in range(3): # 3 classifiers
for i in range(2): # 2 dataset
x,y = preprocess.filtAndShuf(data[m], binaryClass[k,:])
finalWeight[k,:], incorCount, accuracy = perceptron.updateWeight(x, y, finalWeight[k,:], 0, 0)
print(dataName[i],': incorrect number =', incorCount, ' accuracy =', round(accuracy,2))
################################################################################
### Answers to Question5 ###
################################################################################
print('\nQuestion 5, the most discriminative feature')
for i in range(1,5):
weight=np.zeros(2,dtype=float)
x,y = preprocess.filtAndShuf(trainData, binaryClass[1,:])
weight, incorCount, accuracy = perceptron.updateWeight(x[:,[0,i]], y, weight, 0, 1)
print('the feature ',i , 'is converged after', incorCount,'updates')
################################################################################
### Answers to Question6 ###
################################################################################
print('\n\nQuestion 6, multi-class classifier training and their accuracy')
finalWeight = np.zeros(5, dtype=float)
for k in range(3): # 3 classifier
weight=np.zeros((20,5),dtype=float)
for i in range(20): # 20 iteration
x, y = preprocess.filtAndShuf(trainData, multiClass[k,:])
weight[i,:], incorCount, accuracy = perceptron.updateWeight(x, y, weight[i,:], 0, 1)
finalWeight = np.sum(weight, axis=0) / weight.shape[0]
print('\nmulti-class',classifierName[1,k], '\n weight =', np.around(finalWeight[[1,2,3,4]], decimals=2),\
' bias =', np.around(finalWeight[0], decimals=2))
for j in range(2): # 2 dataset
x,y = preprocess.filtAndShuf(data[j], multiClass[k,:])
finalWeight, incorCount, accuracy = perceptron.updateWeight(x, y, finalWeight, 0, 0)
print(' ',dataName[j],': incorrect number =', incorCount, ' accuracy =', round(accuracy,2))
################################################################################
### Answers to Question7 ###
################################################################################
print('\n\nQuestion 7, l2 regularisation')
λ = np.array([0.01, 0.1, 1.0, 10.0, 100.0]) # 5 regularisation coefficient
eta = np.array([1, 1, 1, 0.1, 0.01]) #learning rate
for k in range(3): # 3 classifier
print('\nmulti-class', classifierName[1,k])
finalWeight = np.zeros(5, dtype=float)
for j in range(5): # 5 regularisation coefficient
weight=np.zeros((20,5),dtype=float)
for i in range(20): # 20 iteration
x, y = preprocess.filtAndShuf(trainData, multiClass[k,:]) # binaryClass[k,:] // multiClass[k,:]
weight[i,:], incorCount, accuracy = perceptron.updateWeight(x, y, weight[i,:], λ[j], eta[j])
finalWeight = np.sum(weight, axis=0) / weight.shape[0]
print('\nλ =', λ[j],', weight =', np.around(finalWeight[[1,2,3,4]], decimals=2),\
' bias =', np.around(finalWeight[0], decimals=2))
for m in range(2): # 2 dataset
x,y = preprocess.filtAndShuf(data[m], multiClass[k,:]) # binaryClass[k,:] // multiClass[k,:]
finalWeight, incorCount, accuracy = perceptron.updateWeight(x, y, finalWeight, 0, 0)
print(' ',dataName[m],'accuracy: incorrect number =',\
incorCount, ' accuracy =', round(accuracy,2))