数据如下:

x01=[0.697,0.774,0.634,0.608,0.556,0.403,0.481,0.437,0.666,\
0.243,0.245,0.343,0.639,0.657,0.360,0.593,0.719]
x02=[0.460,0.376,0.264,0.318,0.215,0.237,0.149,0.211,0.091,\
0.267,0.057,0.099,0.161,0.198,0.370,0.042,0.103]
y=[1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0]

x01表示密度,x02表示含糖率,y标志瓜的好坏(1为好,0为坏)

这道题的目的是实现对率回归,那么从3.3节看起。

可以看到我们要求的其实是一个系数序列ω和一个偏差b。简单看过对率回归的介绍后,直接来看推导过程。

将前面的3.19稍微改写一下就可以得到3.22,而由于又有p(y=1|x)+p(y=0|x)=1,所以可以得到3.23和3.24这样的式子。

3.19:ln(y/(1-y))=ωΤx+b

3.22:ln p(y=1|x)/p(y=0|x) =ωΤx+b

按照提示,跳到7.2查看极大似然估计。第一句话指出在估计参数前要假定其具有某种确定的概率分布形式,而在这一题中

我们的概率分布形式就是对率函数,使用极大似然估计就是根据已知的样本来估计参数,解释一下类条件概率指的是在

某种前提下发生某一事件的概率,则P(x|θc)的具体含义就是参数向量为θc时事件x的发生概率。需要厘清一下“概率”和“似然”的区别,

简单来讲概率就是在给定参数时事件发生的可能性,而似然就是在已知随机事件后、概率分布的参数为某一值的可能性(相对于其他

参数取值而言)。具体的解释指路大佬的博客:https://blog.csdn.net/songyu0120/article/details/85059149 讲得非常详尽易懂

而7.9告诉我们的就应当是,已知发生c类事件时,参数θ的值为θc的概率等于参数值为θc时每一个c类事件发生的概率的乘积,

理所当然的,对问题而言最合适的θc就是使7.9式等号右侧的值最大的那个。而7.10中的对数转换操作原理就是将乘法转化为加法,

从而有效防止下溢(超出数据类型所能表示的最小数字),而对数的转换也不会带来信息的损失。

再回到3.25就能看明白它的含义了:对于给定的数据集{(xi,yi)} i∈(1,m) 和一组参数集(ω,b),每个样本属于其真实标记的概率p

的累乘就是这组参数集的似然。而在式中使用了对数似然来防止下溢。

3.25到3.26的操作只是进行了符号的合并简化以及将两种情况的概率巧妙地分离开。

而将3.23与3.34的p1、p0式子代入3.26后,分类讨论y=0、y=1的情况而后观察,就可以把结果合并为3.27的形式,再取负就得到3.27。

因为取负了,所以本来我们要求的是式子的最大值现在变成求式子的最小值。书上应用的是牛顿法。

牛顿法,其核心思想就是泰勒展开。首先讲讲其在方程求解中的应用,然后理解其在最优化的应用会方便很多。

在求解方程的求根公式很复杂甚至没有求根公式时,可以利用牛顿法进行迭代求解,过程就是利用泰勒公式在x0处展开到

一阶,使f(x)=f(x0)+(x-x0)f'(x0)=0,求得一个x1使f(x)比较接近于0,显然,要是我们重复使用这个方法也就是迭代,我们就可以

得到更加准确的答案直到最后在f(x*)=0收敛。

在最优化问题中,如果我们要求一个函数的极大极小问题,显然可以转化为求解函数导数=0的问题,那么就可以使用牛顿法

在方程求解中的方法。因为要求一阶导数的结果等于0,所以对原函数进行两阶泰勒展开,得到

f(x+△x)=f(x+△x)+f'(x+△x)△x+f''(x+△x)△x²/2,两侧对△x求导,在△x无限趋近于0的时候,就可以忽略函数中的△x,从而得到

f'(x)+f''(x)△x=0。则△x=-f'(x)/f''(x)。把△x视作Xn+1(第n+1个迭代解)与Xn(第n个迭代解)的差值,我们就可以得到

迭代解的更新公式,Xn+1=Xn-f'(x)/f''(x)。用矩阵计算代换就可以得到3.29。其中一阶项和二阶项的计算方法都在后面给出,

那么我们只要使用编程实现就行了。

首先,为了方便起见我们要引入numpy这个库来进行矩阵计算,所以对于数据集我们要做一些改动:

x=np.array([[0.697,0.774,0.634,0.608,0.556,0.403,0.481,0.437,0.666,\
0.243,0.245,0.343,0.639,0.657,0.360,0.593,0.719],
[0.460,0.376,0.264,0.318,0.215,0.237,0.149,0.211,0.091,\
0.267,0.057,0.099,0.161,0.198,0.370,0.042,0.103],\
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]])
y=np.array([1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0])
before=np.array([[0],[0],[1]])

将x的数据合并并加入一行1,这个操作对应于3.25和3.26之间那段中的操作,before矩阵就是参数的数据集合,我们不妨设起始参数为0,0,1。

编写程序时要时刻记住x、y、before在书上推导过程中都是单列矩阵,但操作中我们的一些操作会使之变成行矩阵,在后续计算中要及时转置

回来。比如:

np.array([x[:,i]])

这样的操作,目的是从x中取出第i列作为一个单独矩阵,取出后默认是行矩阵,要及时转置。

清楚这点后着手编写各部分的代码。

首先是一阶导的计算:

def fd():
b1 = 0
for i in range(17):
k=np.exp(np.dot(before.T,np.array([x[:,i]]).T))
b1=b1-np.array([x[:,i]])*( y[i]-(k/(1+k)))
return b1

而后是二阶导的计算:

def sd():
b2 = 0
for i in range(17):
k = np.exp(np.dot(before.T,np.array([x[:,i]]).T))
b2=b2+np.dot(np.array([x[:,i]]).T,np.array([x[:,i]])) * (k/(1+k)) * (1-(k/(1+k)))
return b2

最后是主函数,偷个懒不追求最终结果是否收敛的话,限定一个迭代次数上限就完事:

k=1000
while(k):
k-=1
b1=fd()
b2=sd()
before=before-np.dot(linalg.inv(b2),b1.T) print(before)

如果要寻求更精确的结果,可以稍微修改主函数的内容:

mae=0
ima=0
n=0
while(1):
ima=0
for i in range(17):
k=np.dot(before.T,np.array([x[:,i]]).T)
ima=ima+(-y[i]*k+np.log(1+np.exp(k)))
if(np.abs(ima-mae)<=0.001):
break
mae=ima
n=n+1
b1=fd()
b2=sd()
before=before-np.dot(linalg.inv(b2),b1.T)

print('迭代次数:',n)
print('最终参数:',before)

其实就是每次计算出3.27式的值并且在和前次差值小于等于0.00001时退出并输出结果。

结果:

迭代次数: 4
最终参数: [[ 3.15832738]
[12.52119012]
[-4.42886222]]

完整代码:

import math
import numpy as np
from numpy import linalg x=np.array([[0.697,0.774,0.634,0.608,0.556,0.403,0.481,0.437,0.666,\
0.243,0.245,0.343,0.639,0.657,0.360,0.593,0.719],
[0.460,0.376,0.264,0.318,0.215,0.237,0.149,0.211,0.091,\
0.267,0.057,0.099,0.161,0.198,0.370,0.042,0.103],\
[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]])
y=np.array([1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0])
before=np.array([[0],[0],[1]]) def fd():
b1 = 0
for i in range(17):
k=np.exp(np.dot(before.T,np.array([x[:,i]]).T))
b1=b1-np.array([x[:,i]])*( y[i]-(k/(1+k)))
return b1 def sd():
b2 = 0
for i in range(17):
k = np.exp(np.dot(before.T,np.array([x[:,i]]).T))
b2=b2+np.dot(np.array([x[:,i]]).T,np.array([x[:,i]])) * (k/(1+k)) * (1-(k/(1+k)))
return b2 mae=0
ima=0
n=0
while(1):
ima=0
for i in range(17):
k=np.dot(before.T,np.array([x[:,i]]).T)
ima=ima+(-y[i]*k+np.log(1+np.exp(k)))
if(np.abs(ima-mae)<=0.000001):
break
mae=ima
n=n+1
b1=fd() b2=sd()
before=before-np.dot(linalg.inv(b2),b1.T) print('迭代次数:',n)
print('最终参数:',before)

西瓜书3.3 尝试解题(python)对率回归 极大似然估计的更多相关文章

  1. python实现简单决策树(信息增益)——基于周志华的西瓜书数据

    数据集如下: 色泽 根蒂 敲声 纹理 脐部 触感 好瓜 青绿 蜷缩 浊响 清晰 凹陷 硬滑 是 乌黑 蜷缩 沉闷 清晰 凹陷 硬滑 是 乌黑 蜷缩 浊响 清晰 凹陷 硬滑 是 青绿 蜷缩 沉闷 清晰 ...

  2. 决策树ID3原理及R语言python代码实现(西瓜书)

    决策树ID3原理及R语言python代码实现(西瓜书) 摘要: 决策树是机器学习中一种非常常见的分类与回归方法,可以认为是if-else结构的规则.分类决策树是由节点和有向边组成的树形结构,节点表示特 ...

  3. 朴素贝叶斯python代码实现(西瓜书)

    朴素贝叶斯python代码实现(西瓜书) 摘要: 朴素贝叶斯也是机器学习中一种非常常见的分类方法,对于二分类问题,并且数据集特征为离散型属性的时候, 使用起来非常的方便.原理简单,训练效率高,拟合效果 ...

  4. 孤荷凌寒自学python第五十九天尝试使用python来读访问远端MongoDb数据服务

    孤荷凌寒自学python第五十九天尝试使用python来读访问远端MongoDb数据服务 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第五天.今天的感觉是,mongoDB数 ...

  5. 孤荷凌寒自学python第五十七天初次尝试使用python来连接远端MongoDb数据库

    孤荷凌寒自学python第五十七天初次尝试使用python来连接远端MongoDb数据库 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第三天.感觉这个东西学习起来还是那么困 ...

  6. 孤荷凌寒自学python第五十二天初次尝试使用python读取Firebase数据库中记录

    孤荷凌寒自学python第五十二天初次尝试使用python读取Firebase数据库中记录 (完整学习过程屏幕记录视频地址在文末) 今天继续研究Firebase数据库,利用google免费提供的这个数 ...

  7. 孤荷凌寒自学python第五十一天初次尝试使用python连接Firebase数据库

    孤荷凌寒自学python第五十一天初次尝试使用python连接Firebase数据库 (完整学习过程屏幕记录视频地址在文末) 今天继续研究Firebase数据库,利用google免费提供的这个数据库服 ...

  8. 周志华-机器学习西瓜书-第三章习题3.5 LDA

    本文为周志华机器学习西瓜书第三章课后习题3.5答案,编程实现线性判别分析LDA,数据集为书本第89页的数据 首先介绍LDA算法流程: LDA的一个手工计算数学实例: 课后习题的代码: # coding ...

  9. LASSO回归与L1正则化 西瓜书

    LASSO回归与L1正则化 西瓜书 2018年04月23日 19:29:57 BIT_666 阅读数 2968更多 分类专栏: 机器学习 机器学习数学原理 西瓜书   版权声明:本文为博主原创文章,遵 ...

  10. 决策树 机器学习,西瓜书p80 表4.2 使用信息增益生成决策树及后剪枝

    使用信息增益构造决策树,完成后剪枝 目录 使用信息增益构造决策树,完成后剪枝 1 构造决策树 1 根结点的选择 色泽 信息增益 根蒂 信息增益 敲声 信息增益 纹理 信息增益 脐部 信息增益 触感 信 ...

随机推荐

  1. matlab算符合集

    1.逻辑算符 1)且 : A & B -- 两个逻辑数组之间 逐个元素 进行逻辑"与"操作 AB可为矩阵. 首先判断表达式A的逻辑值,然后判断B,继而进行逻辑"与 ...

  2. Mybatis二级缓存(2)

    10.3.一级缓存的原理 10.3.3 一级缓存的测试

  3. 在idea中查看jar包源码

    文章目录 准备jar包 idea打开文件夹 最后一步 准备jar包 例如,我准备看resin的jar,在桌面准备了一份 idea打开文件夹 在idea中file====>open=====> ...

  4. xfce-debian10 英文环境安装配置记录

    Centos还没有用利索(因为我听说debian是更纯正的社区开源项目???可是这对于我这样毫无技术菜鸟来说有什么关系呢???可是耐不住心中的悸动???悸动又从哪里了呢???哎,不管了),突然心血来潮 ...

  5. 详解 C++ 左值、右值、左值引用以及右值引用

    一.左值和右值 1.左值 [可以取地址的对象就是左值] 左值是一个表示数据的表达式,比如:变量名.解引用的指针变量.一般地,我们可以获取它的地址和对它赋值,但被 const 修饰后的左值,不能给它赋值 ...

  6. Pyscript使用本地Pyodide配置方法

    背景 Pyscript工程本身很小,KB级别,引用的Pyodide工程比较大,因为包含了各种类库的wasm文件,默认引用了cdn上的文件,cdn上的文件又在外网,访问会中断导致不可用,于是需要使用本地 ...

  7. Codeforces 1208F Bits And Pieces

    题目描述 You are given an array a of n integers. You need to find the maximum value of ai|(aj&ak) ov ...

  8. Android NDK build vsomeip3

    Build Boost for Android https://github.com/moritz-wundke/Boost-for-Android set the NDK_ROOT environm ...

  9. nginx auth_basic uwsgi 目录简易认证。

    mkdir /etc/nginx/conf.d/auth_pwd touch /etc/nginx/conf.d/auth_pwd/xx.pwd htpasswd -c -d /etc/nginx/c ...

  10. 算法图解 - 第1章 二分查找 与大O

    例子:猜一个1到100之间的数,最多猜几次? # 最糟糕的猜法:一个一个的猜 - 最多查找次数: n  - 运行时间: O(n) # 二分查找:在有序的一组数中猜一个数,对半猜.找到返回其位置(索引) ...