SDU机器学习作业心得3

这篇博客详细记录了山东大学《机器学习》课程上机实验的过程,主要涉及Parzen窗估计方法和k-近邻概率密度估计。作者分析并解决了4.3节和4.4节的问题,包括一维和二维数据的分类,以及三维数据的k-近邻概率密度估计,并讨论了k值对分类结果的影响。
摘要由CSDN通过智能技术生成

山东大学《机器学习》实验报告

---- 上机练习4.3节2题,4.4节3题

软件16-6 李昊 201600301309

问题背景:

题目给出了三个类别的三维数据各十个如下:

1543120260517

    1. 使用Parzen窗估计方法,h=1使用表中数据训练,然后对样本点分类,样本点为[0.5,1.0,0.0]T,[0.31,1.51,-0.50]T,[-0.3,0.44,-0.1]T

    2)令h=0.1,重复第一问

  1. 1)对于一维的情况,当有n个数据样本点时,进行k-近邻概率密度估计。对表格中的类别w3中的特征x1,用程序画出当k=1、3、5时概率密度估计结果。

    2)对于二维的情况,同第一问,数据变为类别w2中的特征(x1,x2)T。

    3)对表格中的三个类别的三维特征,使用k-近邻概率密度估计方法。并且对下列点处的概率密度进行估计:[-0.41,0.82,0.88]T,[0.14,0.72,4.1]T,[-0.81,0.61,-0.38]T。

问题分析:

对于4.3节中的问题。

题目给出了窗函数,由于是正比关系,比例系数不影响分类,所以我们假设
φ ( ( x − x i ) / h ) = e x p [ − ( x − x i ) t ( x − x i ) / ( 2 h 2 ) ] \varphi ((x-x_i)/h)=exp[-(x-x_i)^t(x-x_i)/(2h^2)] φ((xxi)/h)=exp[(xxi)t(xxi)/(2h2)]
所以根据书中给出的公式
k n = ∑ 1 n φ ( ( x − x i ) / h ) k_n=\sum_1^n \varphi((x-x_i)/h) kn=1nφ((xxi)/h)

p n ( x ) = 1 / n ∑ 1 n ( 1 / V n ) φ ( ( x − x i ) / h ) = 1 / n ∑ 1 n e x p [ − ( x − x i ) t ( x − x i ) / ( 2 h 2 ) ] / h 3 p_n(x)=1/n\sum_1^n(1/V_n) \varphi((x-x_i)/h)=1/n\sum_1^nexp[-(x-x_i)^t(x-x_i)/(2h^2)]/h^3 pn(x)=1/n1n(1/Vn)φ((xxi)/h)=1/n1nexp[(xxi)t(xxi)/(2h2)]/h3

可以看出,这个过程是对一系列关于x和xi的函数作平均。

我们得出这个表达式以后,剩下的就只是编程体现了。

对于4.4节中的问题。

第一问中,需生成一系列样本点,然后根据不同的k来计算它的V,这样就可以获得一系列的概率,进而画出结果。在求V时,重点是求出r,而r应该是训练数据中的,距离样本点最近的k个点中,最远的那个和样本点之间的距离。在这之后,我们就可以有这个公式:
p n ( x ) = ( k n / n ) / V n p_n(x)=(k_n/n)/V_n pn(x)=kn/n/Vn
第二问与第一问类似。

第三问的一个不确定点就是k的选择,k过小,可能不准确;k过大,又可能过拟合。所以,我们选择了k=3。有了k,再用与之前类似的方法求出V,再比较对应三个类别的概率大小即可解决。

问题解决:

读入数据还是用的前几次试验的方式。

首先解决4.3节中的问题。

我们对于这三个样本点,分别计算出其对于三个类别的p10(x),然后比较其大小即可。

下面是我计算parzen窗估计的代码:

def parzen(point,h):#Parzen
        temp=0
        for i in range(10):
                temp+=math.exp(-(point-w1[:,i-1]).T*(point-w1[:,i-1])/(2*(h**2)))/h**3
        out1=0.1*temp
        temp=0
        for i in range(10):
                temp+=math.exp(-(point-w2[:,i-1]).T*(point-w2[:,i-1])/(2*(h**2)))/h**3
        out2=0.1*temp
        temp=0
        for i in range(10):
                temp+=math.exp(-(point-w3[:,i-1]).T*(point-w3[:,i-1])/(2*(h**2)))/h**3
        out3=0.1*temp
        print('the p10(x) of ','\n',point,'for w123 with h=',h,' is ','\n',out1,out2,out3)
        tst=[out1,out2,out3]
        i=1
        for t in tst:
                if t==max(tst):
                        print("This point due to kind",i)
                i+=1
        print("")

由于这个代码传入不同的点与h可以相应的计算,而一二两问只是h不同,所以我把两问一次性算出来了。

parzen(point1,1)
parzen(point2,1)
parzen(point3,1)
parzen(point1,0.1)
parzen(point2,0.1)
parzen(point3,0.1)

下面是运行结果。

1543124063707

经过验证,结果与分类都正确。

接下来解决4.4节的问题。

1)首先我们创建0-3之间的100个随机的数据样本。

list1=[]
for i in range(100):
    list1.append(random.uniform(0,3))

然后开始求r,r是第k远的点,所以我们首先要求出样本点与数据集的距离,然后排序,取第k个元素,得到r。

得到r以后,进而求出pnx,重复求出所有的点,然后用plt输出。代码如下:

首先初始化样本集。

list1=[]
for i in range(100):
        list1.append(random.uniform(0,3))

接下来是主程序。

def k_neighbor(list1,k):
        outlist=[]
        for i in range(100):
                temp=list1[i]
                j=w3[0]
                #print(j)
                h=[]
                r_list=[]
                for i in range(10):
                        h.append(float(j[:,i]))
                for i in h:
                        r_list.append(abs(i-temp))
                r_list.sort()
                r=r_list[k-1]                                
                outlist.append((k/10)/(2*r))
        
        plt.title(k)
        plt.xlabel('x')
        plt.ylabel('p(x)')
        plt.plot(list1,outlist,'ro')
        plt.show()
        
w1,w2,w3=getmat()
k_neighbor(list1,1)
k_neighbor(list1,3)
k_neighbor(list1,5)

输出结果如下:

1543136979405

1543136995125

1543137009506

2)与第一问类似。这一问的难点我觉得反而是plt的三维表示,对于没用过plt的人来说是一个挑战,我弄的乱七八糟,好歹功能实现了。

代码如下:

首先初始化样本集:经过观察,样本处于-3到3之间

list1=[]
for i in range(100):
        list1.append(random.uniform(-3,3))
list2=[]
for i in range(100):
        list2.append(random.uniform(-3,3))

然后是主程序:

def k_neighbor2(list1,list2,k):
        outlist=[]
        #print(w2[0:2])
        for i in range(100):
                temp=np.mat([list1[i],list2[i]]).T
                j=w2[0:2]
                r_list=[]
                for i in range(10):
                        h=j[:,i]
                        t=temp-h
                        r_list.append((float(t[0])**(2)+float(t[1])**(2))**(0.5))
                r_list.sort()
                r=r_list[k-1] 
                outlist.append((k/10)/(math.pi*r*r))
        fig=plt.subplot(111,projection='3d')
        #fig.xlim(-3,3)
        #fig.ylim(-3,3)
        fig.plot(list1,list2,outlist,'ro')
        plt.show()

输出结果如下:

k=1

1543141974916

k=3

1543141996481

k=5

1543142011671

3)第三问就是推1及2的过程了,我们选择k=3,因为k=1不明显,而k=5可以在上图中看到,有些过拟合,因为“山峰”过多。

过程与第二问比较类似,代码如下:

数据初始化:

point4=(mat([-0.41,0.82,0.88])).T
point5=(mat([0.14,0.72,4.1])).T
point6=(mat([-0.81,0.61,-0.38])).T

主程序:

def k_neighbor3(point):
        r_list1=[]
        r_list2=[]
        r_list3=[]
        for i in range(10):
                t1=w1[:,i]-point
                t2=w2[:,i]-point
                t3=w3[:,i]-point
                r_list1.append((float(t1[0])**2+float(t1[1])**2+float(t1[2])**2)**(0.5))
                r_list2.append((float(t2[0])**2+float(t2[1])**2+float(t2[2])**2)**(0.5))
                r_list3.append((float(t3[0])**2+float(t3[1])**2+float(t3[2])**2)**(0.5))
        r_list1.sort()
        r_list2.sort()
        r_list3.sort()
        r1=r_list1[2]
        r2=r_list2[2]
        r3=r_list3[2]
        p1=(9/40)/(math.pi*(r1**3))
        p2=(9/40)/(math.pi*(r2**3))
        p3=(9/40)/(math.pi*(r3**3))
        print('the pnx of point','\n',point,'\n','for w123 with k=3 is','\n',p1,p2,p3)
        tst=[p1,p2,p3]
        i=1
        for t in tst:
                if t==max(tst):
                        print("This point due to kind",i)
                i+=1
        print("")  

输出结果如下:

1543143831387

最后总代码中整合输出了所有题目的答案,不再赘述。

感想:

Parzen窗方法相对简单,理解过程、根据公式就可以解答。

对于K-近邻方法,通过试验过程我们可以发现,对于不同的k,结果也不相同,根据对于k的意义的思考,我觉得,当k过小时,不能很好的有一个分类的作用,因为只要满足很简单的条件就可以符合;而当k过大时,可以想象成有很复杂的条件来让这个点符合我们的标准,就会造成符合的点与我们的数据点过于相似,这显然也是不合适的。我们可以类比一下,假如我们是通过头发长短来区分男女,在我们的数据中,发短的是男的,发长的是女的,数据中男的发长3cm,但是一个发长2.5cm的人来了,却有很大可能被分类到女的中,这就是因为k的取值过大,导致模型认为只有3cm的才是男的。

除此之外,我还有一个深刻的感受,就是从0到1的过程永远是最难的,而从1到2简单很多。在试验之前,我从没接触过plt和对随机样本的估计。这就导致在对问题的理解上出现了很多偏差。好在有同学,有网络。慢慢的理解以后,才发现那些困难也不过如此。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值