zoukankan      html  css  js  c++  java
  • 機器學習基石 机器学习基石(Machine Learning Foundations) 作业1 习题解答 (续)

    这里写的是  习题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)

    为了更好的理解   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)

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

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

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

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

    C++ 版:

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

    第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)

    结果:

  • 相关阅读:
    vim+makefile入门编辑,编译,差错实例
    vim操作备忘录
    vim学习、各类插件配置与安装
    ubuntu命令行下java工程编辑与算法(第四版)环境配置
    【RabbitMQ】命令行使用学习
    【Docker】RabbitMQ使用学习
    Jmeter如何把响应数据的结果保存到本地的一个文件
    Selenium + Python 自动化测试环境搭建
    Jmeter监控服务器-CPU,Memory,Disk,Network性能指标
    Jmeter 聚合报告---测试结果分析
  • 原文地址:https://www.cnblogs.com/devilmaycry812839668/p/9021237.html
Copyright © 2011-2022 走看看