这里写的是  习题1 中的    18 , 19, 20 题的解答。

Packet 方法,我这里是这样认为的,它所指的贪心算法是不管权重更新是否会对train data有改进都进行修正,因为这里面没有区分是否可以线性分割,如果线性可分那么每次的更新都注定是要使train data的分割效果得到提升,但是如果不是线性可分的,那么并不是每次的权重修正都可以使效果得到提升。 这时候的贪心算法是指不考虑每次权重的修正是否可以使优化效果得到提升,有错误的分割则进行一次权重修正。这种情况下我们不能保证一定会得到完美的分割,算法是否可以达到稳定而终止也是不确定的,该情况下则设置权重的最多更新次数。同时,将所有更新权重后得到的权重之中获得最优的权重。

根据上一个博客的实验,发现不管是不是线性可分的数据集,在权重更新的时候都不能保证一定会使数据分割的效果得到提升,也就是说每次的权重修正并不一定会使训练误差减小,基本可以说训练误差会随着权重修正而上下起伏的,但是线性可分的数据最终会得到完全的正确分割,线性不可分的数据最终也无法得到完全正确的分割,所以这时候Packet 方法上场了,也就是说对于不可以线性分割的数据我们如果还是用完全分割作为终止条件那么算法将永远不会停止,所以我们在Packet算法中以权重UPDATE的次数作为终止条件,又因为不论是线性可分还是不可分的数据集权重的优化效果都是上下起伏的,所以在Packet方法中我们只选择权重更新历史记录中最优的结果作为实验的最终答案。


第18题, Python编写:

#!/usr/bin/env python3
#encoding:UTF-8
import random
import copy
import urllib.request

L=4
url_1="https://www.csie.ntu.edu.tw/~htlin/mooc/datasets/mlfound_math/hw1_18_train.dat"
url_2="https://www.csie.ntu.edu.tw/~htlin/mooc/datasets/mlfound_math/hw1_18_test.dat"


"数据读入"
def dataLoad(url):
repones=urllib.request.urlopen(url)
dataList=repones.readlines()
dataList=[(float(v) for v in k.strip().split()) for k in dataList]
dataList=[(1.0,)+tuple(k) for k in dataList]
return dataList


def test(dataList, w):
test_error=0

def sign(item):
s=0
for k in range(L+1):
s+=w[k]*item[k]
if(s>0):return 1
else:return -1

for item in dataList:
value=sign(item)
if(value!=item[-1]):
test_error+=1

error_rate=test_error/len(dataList)
return error_rate


#训练过程
def train(train_data, test_data):
train_time=0
w_best=[0]*(L+1)
w_candidate=[0]*(L+1)

def sign(item, w):
s=0
for k in range(L+1):
s+=w[k]*item[k]
if(s>0):return 1
else:return -1

def w_change(item):
nonlocal w_candidate
for k in range(L+1):
w_candidate[k]+=item[k]*item[-1]

error_1=test(train_data, w_best)

while(True):
for item in train_data:
value=sign(item, w_candidate)
if(value!=item[-1]):
w_change(item)
train_time+=1

error_2=test(train_data, w_candidate)
if(error_2<error_1):
w_best=copy.copy(w_candidate)
error_1=error_2

if(train_time==50):
return w_best

if __name__=="__main__":
train_data=dataLoad(url_1) #train_data
test_data=dataLoad(url_2) #train_data

error=[]

for i in range(2000):
"打乱顺序"
random.shuffle(train_data)
w=train(train_data, test_data)
e=test(test_data, w)
print("第", i, "次实验,误差:", e)
error.append(e)
print(sum(error)/2000)

機器學習基石 机器学习基石(Machine Learning Foundations) 作业1 习题解答 (续)_机器学习

为了更好的理解   Packet 方法, 下面给出权重更新的部分过程:

第 370 次实验,误差: 0.154

error_1 0.39

error_2 0.61

error_2 0.346

error_2 0.39

error_2 0.374

error_2 0.61

error_2 0.316

error_2 0.61

error_2 0.364

error_2 0.608

error_2 0.212

error_2 0.604

error_2 0.186

error_2 0.61

error_2 0.264

error_2 0.388

error_2 0.14

error_2 0.526

error_2 0.332

error_2 0.332

error_2 0.368

error_2 0.422

error_2 0.226

error_2 0.564

error_2 0.224

error_2 0.478

error_2 0.246

error_2 0.386

error_2 0.204

error_2 0.422

error_2 0.264

error_2 0.262

error_2 0.264

error_2 0.434

error_2 0.226

error_2 0.53

error_2 0.234

error_2 0.39

error_2 0.232

error_2 0.418

error_2 0.2

error_2 0.48

error_2 0.21

error_2 0.542

error_2 0.234

error_2 0.538

error_2 0.232

error_2 0.558

error_2 0.25

error_2 0.466

error_2 0.332

第 371 次实验,误差: 0.138


error_1 0.39

error_2 0.61

error_2 0.448

error_2 0.39

error_2 0.348

error_2 0.61

error_2 0.382

error_2 0.602

error_2 0.326

error_2 0.488

error_2 0.3

error_2 0.526

error_2 0.164

error_2 0.61

error_2 0.21

error_2 0.61

error_2 0.262

error_2 0.61

error_2 0.19

error_2 0.604

error_2 0.252

error_2 0.556

error_2 0.176

error_2 0.572

error_2 0.208

error_2 0.5

error_2 0.252

error_2 0.454

error_2 0.228

error_2 0.378

error_2 0.61

error_2 0.388

error_2 0.334

error_2 0.386

error_2 0.26

error_2 0.516

error_2 0.244

error_2 0.374

error_2 0.298

error_2 0.248

error_2 0.372

error_2 0.156

error_2 0.602

error_2 0.128

error_2 0.382

error_2 0.138

error_2 0.38

error_2 0.11

error_2 0.568

error_2 0.142

error_2 0.588

第 372 次实验,误差: 0.106

第  19题:

#!/usr/bin/env python3
#encoding:UTF-8
import random
import copy
import urllib.request

L=4
url_1="https://www.csie.ntu.edu.tw/~htlin/mooc/datasets/mlfound_math/hw1_18_train.dat"
url_2="https://www.csie.ntu.edu.tw/~htlin/mooc/datasets/mlfound_math/hw1_18_test.dat"


"数据读入"
def dataLoad(url):
repones=urllib.request.urlopen(url)
dataList=repones.readlines()
dataList=[(float(v) for v in k.strip().split()) for k in dataList]
dataList=[(1.0,)+tuple(k) for k in dataList]
return dataList


def test(dataList, w):
test_error=0

def sign(item):
s=0
for k in range(L+1):
s+=w[k]*item[k]
if(s>0):return 1
else:return -1

for item in dataList:
value=sign(item)
if(value!=item[-1]):
test_error+=1

error_rate=test_error/len(dataList)
return error_rate


#训练过程
def train(train_data):
train_time=0
w_best=[0]*(L+1)
w_candidate=[0]*(L+1)

def sign(item, w):
s=0
for k in range(L+1):
s+=w[k]*item[k]
if(s>0):return 1
else:return -1

def w_change(item):
nonlocal w_candidate
for k in range(L+1):
w_candidate[k]+=item[k]*item[-1]

#error_1=test(train_data, w_best)
#print("error_1", error_1)
while(True):
for item in train_data:
value=sign(item, w_candidate)
if(value!=item[-1]):
w_change(item)
train_time+=1

#error_2=test(train_data, w_candidate)
#print("error_2", error_2)
#if(error_2<error_1):
# w_best=copy.copy(w_candidate)
# error_1=error_2

if(train_time==50):
#return w_best
return w_candidate

if __name__=="__main__":
train_data=dataLoad(url_1) #train_data
test_data=dataLoad(url_2) #train_data

error=[]

for i in range(2000):
"打乱顺序"
random.shuffle(train_data)
w=train(train_data)
e=test(test_data, w)
print("第", i, "次实验,误差:", e)
error.append(e)
print(sum(error)/2000)

機器學習基石 机器学习基石(Machine Learning Foundations) 作业1 习题解答 (续)_ooc_02


答案和 网上C++版的不太一样,那一版是0.27。


问题在哪,不知道,还在寻找中。

 经过比对,最终找出了原因, c++版只进行了49次修正,而我写的是进行了50次修正,修改如下:

機器學習基石 机器学习基石(Machine Learning Foundations) 作业1 习题解答 (续)_ooc_03



不随机情况下,Python 版结果:

機器學習基石 机器学习基石(Machine Learning Foundations) 作业1 习题解答 (续)_ooc_04


C++ 版:

機器學習基石 机器学习基石(Machine Learning Foundations) 作业1 习题解答 (续)_机器学习_05

可以看到其结果大致相同,  错误排除成功。

第20题, 修改修正次数:

#!/usr/bin/env python3
#encoding:UTF-8
import random
import copy
import urllib.request

L=4
url_1="https://www.csie.ntu.edu.tw/~htlin/mooc/datasets/mlfound_math/hw1_18_train.dat"
url_2="https://www.csie.ntu.edu.tw/~htlin/mooc/datasets/mlfound_math/hw1_18_test.dat"


"数据读入"
def dataLoad(url):
repones=urllib.request.urlopen(url)
dataList=repones.readlines()
dataList=[(float(v) for v in k.strip().split()) for k in dataList]
dataList=[(1.0,)+tuple(k) for k in dataList]
return dataList


def test(dataList, w):
test_error=0

def sign(item):
s=0
for k in range(L+1):
s+=w[k]*item[k]
if(s>0):return 1
else:return -1

for item in dataList:
value=sign(item)
if(value!=item[-1]):
test_error+=1

error_rate=test_error/len(dataList)
return error_rate


#训练过程
def train(train_data, test_data):
train_time=0
w_best=[0]*(L+1)
w_candidate=[0]*(L+1)

def sign(item, w):
s=0
for k in range(L+1):
s+=w[k]*item[k]
if(s>0):return 1
else:return -1

def w_change(item):
nonlocal w_candidate
for k in range(L+1):
w_candidate[k]+=item[k]*item[-1]

error_1=test(train_data, w_best)

while(True):
for item in train_data:
value=sign(item, w_candidate)
if(value!=item[-1]):
w_change(item)
train_time+=1

error_2=test(train_data, w_candidate)
if(error_2<error_1):
w_best=copy.copy(w_candidate)
error_1=error_2

if(train_time==100):
return w_best

if __name__=="__main__":
train_data=dataLoad(url_1) #train_data
test_data=dataLoad(url_2) #train_data

error=[]

for i in range(2000):
"打乱顺序"
random.shuffle(train_data)
w=train(train_data, test_data)
e=test(test_data, w)
print("第", i, "次实验,误差:", e)
error.append(e)
print(sum(error)/2000)


结果:

機器學習基石 机器学习基石(Machine Learning Foundations) 作业1 习题解答 (续)_数据_06