统计学习⽅法第⼆版李航【学习笔记Python代码】
前⾔
《统计学习⽅法》和《机器学习》这两本书,⼤概是做科研的⼩伙伴都避不开的必读书吧。笔者在很久前就已经学过该书了,但是因为先前学完没有做⼀个详细的整理总结。然后最近实验室招新,需要带⼀带⼩朋友学习这本书,故重温该书且在此整理记录,望对⼤家有所帮助!
第⼀章统计学习及监督学习概论
这⼀章主要都是些概念,⼤家感兴趣的话可以去看我的另⼀篇博客,讲得更加简洁明了:
第⼆章感知机
这⾥先附上复现代码。
class Model:
def__init__(self):
self.w = np.ones(len(data[0])-1, dtype=np.float32)
self.b =0
self.l_rate =0.1
# self.data = data
def sign(self, x, w, b):
y = np.dot(x, w)+ b
return y
# 随机梯度下降法
def fit(self, X_train, y_train):
is_wrong =False
while not is_wrong:
wrong_count =0
for d in range(len(X_train)):
X = X_train[d]
y = y_train[d]
if y * self.sign(X, self.w, self.b)<=0:
self.w = self.w + self.l_rate*np.dot(y, X)content啥意思
self.b = self.b + self.l_rate*y
wrong_count +=1
if wrong_count ==0:
is_wrong =True
return'Perceptron Model!'
def score(self):
pass
下载训练数据:
import pandas as pd
import numpy as np
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label']= iris.target
df.label.value_counts()
plt.scatter(df[:50]['sepal length'], df[:50]['sepal width'], label='0')
plt.scatter(df[50:100]['sepal length'], df[50:100]['sepal width'], label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
plt.show()
data = np.array(df.iloc[:100,[0,1,-1]])
X, y = data[:,:-1], data[:,-1]
y = np.array([1if i ==1else-1for i in y])
perceptron = Model()
perceptron.fit(X, y)
测试:
x_points = np.linspace(4,7,10)
y_ =-(perceptron.w[0]*x_points + perceptron.b)/perceptron.w[1]
plt.plot(x_points, y_)
plt.plot(data[:50,0], data[:50,1],'bo', color='blue', label='0')
plt.plot(data[50:100,0], data[50:100,1],'bo', color='orange', label='1')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.legend()
plt.show()
第三章 k近邻法
定义
近邻法 (k-nearest neighbor,k -NN) 种基本分类与回归⽅法。本书只讨论分类问题中的 k近邻法。 近邻法的输⼊为实例的特征向量,对应于特征空间的点:输出为实例的类别,可以取多类。 近邻法假设给定 个训练数据集, 其中的实例类别⼰定。分类时,对新的实例,根据其个最近邻的训练实例的类别,通过多数表决等⽅式进⾏预测 因此 近邻法不具有显式的学习过程。
多数表决简单理解即为哪种类别数量多对应的分类结果就是哪种。
⽽不显式学习简单理解即为,不像感知机等⽅法需要预先训练好⼀个模型,k近邻是每次分类就利⽤⼀遍训练集⾥的数据,
k近邻算法
⼤致理解的话,先是输⼊训练集:
输出即为实例x所属的类别。
算法流程⼤致如下:
(1)先是计算x与训练集中给定数据的距离度量最⼩的k个数据(这⾥的距离度量通常是求lp距离,⼀般为l2,即欧式距离)
(2)根据决策⽅法即多数表决⽅法来求出实例x所属类别:
k值的选择
⼤家肯定都能想到k值的选择必然会对结果产⽣极⼤影响,那么k值取⼤取⼩对应的会有什么影响呢?
选⼩了:学习的近似误差会减⼩,但是估计误差会增⼤。什么意思呢?就是我对于距离实例x的近似点会⾮常敏感,那如果刚好我的近似点就是误差点的话,那么我的结果就会出错。这样的话便容易出现过拟合。
选⼤了:对应的可以减⼩我的估计误差,但是相对的那些原本不那么近似的点也会被我纳⼊考量,使得发⽣错误。同时相对的模型也会变得简单。往极端了想,k值等于我训练集的⼤⼩,那岂不是巨简单,直接给出我训练集⾥⾯类别占⽐最⼤的最可以了,但这样肯定是有很⼤问题的。
在应⽤中 ⼀般取 ⽐较⼩的数值,且通常采⽤交叉验证法来选取最优的k值。
kd树
书本⾥⾯最开始讲得⾮常⽣硬,这⾥我打算结合具体题⽬来讲。
先附⼀下题⽬:
上图其实还没有画完整,我先给它补全。
下⾯介绍解题步骤:
(1)先建⽴⼀个kd树,注意这⾥的kd树是⼆叉树。
最开始选哪⼀个作为根节点呢?聪明的⼩朋友可以发现A是上述的根节点,选它作为根节点的原因是因为它的y坐标⼤⼩是所有y坐标⼤⼩的中位数。所以我们每次分割的时候都是选其中位数的点(如果中位数的点有两个的话就任⼀都可)。同样的道理,为啥第⼆条线不是经过的G或者E,⽽是经过C(即选C点为⼦结点),因为C的横坐标⼤⼩是在gce点中的中位数。以此类推。
提醒⼀下啊,我们可以先往x轴⽅向分割,也可以往y轴⽅向切割,然后x和y轴⽅向交替切割。
(2)选择⼀个叶节点作为“当前最近点”,叶节点上图⼀共有四个,分别是g、e、f和d点。那为啥选d呢?
是这样⼦的,实例s点是不是⽐根节点a的纵坐标要⼩(之所以⽐纵坐标是因为这⾥是从纵坐标开始切割的),既然⼩的话那我们就选A下⾯这块区域,这块区域显然是由点B总管的,那这个时候同理再与点B⽐较⼀下横坐标,是不是要⽐点B⼤,那⼤的话就选右边这块区域,这个时候显然就只剩下点D了,所以确定点D为当前最近点。
(3)确定完某⼀个叶节点为当前最近点后,开始递归向上回退,退到⽗节点B,看看⽗节点B会不会更近,好的不会,那再看看⽗节点B它的另⼀个⼦区域有没有点⽐当前最近点还近。具体怎么检查呢,我们以实例点S与当前最近点D的距离为半径画个圆,看看这个区域会不会跟这个圆相交,不会的话就直接放弃,会的话移动到该结点检查是否需要更新当前最近点。
vscode制作动态网页好的,经过上述我们发现点B管的区域也没有⽤了,那我们再回退到点B的⽗节点,重复上述⼯作:即看点A会不会更近,不会,那就看点A 的另⼀个⼦结点C有没有跟我相交,有,那移动到点C,看看与其相交的右区域有⽆点包含在圆⾥⾯,即距离更近,有,ok,完事。
实现代码
附下实现kd树实现代码:
import numpy as np
from math import sqrt
import pandas as pd
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
del_selection import train_test_split
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris.feature_names)
df['label']= iris.target
data = np.array(df.iloc[:100,[0,1,-1]])
train, test = train_test_split(data, test_size=0.1)
指针变量是存放地址的变量
train, test = train_test_split(data, test_size=0.1)
x0 = np.array([x0 for i, x0 in enumerate(train)if train[i][-1]==0])
x1 = np.array([x1 for i, x1 in enumerate(train)if train[i][-1]==1])
def show_train():
plt.scatter(x0[:,0], x0[:,1], c='pink', label='[0]')
plt.scatter(x1[:,0], x1[:,1], c='orange', label='[1]')
plt.xlabel('sepal length')
plt.ylabel('sepal width')
class Node:
def__init__(self, data, depth=0, lchild=None, rchild=None):
self.data = data
self.depth = depth
self.lchild = lchild
class KdTree:
def__init__(self):
self.KdTree =None
self.n =0
小白学python买什么书
def create(self, dataSet, depth=0):
if len(dataSet)>0:
m, n = np.shape(dataSet)
self.n = n -1
axis = depth % self.n
mid =int(m /2)
dataSetcopy =sorted(dataSet, key=lambda x: x[axis])
node = Node(dataSetcopy[mid], depth)
if depth ==0:
self.KdTree = node
node.lchild = ate(dataSetcopy[:mid], depth+1)
return None
def preOrder(self, node):
if node is not None:
print(node.depth, node.data)
self.preOrder(node.lchild)
self.hild)
def search(self, x, count=1):
nearest =[]
for i in range(count):
nearest.append([-1,None])
def recurve(node):
if node is not None:
axis = node.depth % self.n
daxis = x[axis]- node.data[axis]
if daxis <0:
recurve(node.lchild)
else:
vbscript入门书籍hild)
dist = sqrt(sum((p1 - p2)**2for p1, p2 in zip(x, node.data))) for i, d in arest):
if d[0]<0or dist < d[0]:
break
n =arest[:,0]).count(-1)
arest[-n-1,0]>abs(daxis):
if daxis <0:
hild)
else:
recurve(node.lchild)
recurve(self.KdTree)
contenteditable属性默认为trueknn = arest[:,1]
belong =[]
for i in knn:
belong.append(i.data[-1])
b =max(set(belong), unt)
arest, b
kdt = KdTree()
kdt.preOrder(kdt.KdTree)
score =0
for x in test:
input('press Enter to show next:')
show_train()
plt.scatter(x[0], x[1], c='red', marker='x')# 测试点
near, belong = kdt.search(x[:-1],5)# 设置临近点的个数
if belong == x[-1]:
score +=1
print("test:")
print(x,"predict:", belong)
print("nearest:")
for n in near:
print(n[1].data,"dist:", n[0])
plt.scatter(n[1].data[0], n[1].data[1], c='green', marker='+')# k个最近邻点
plt.legend()
plt.show()
score /=len(test)
print("score:", score)
结束语
正在不断更新中。。。
以后我会在博客记录⾃⼰学习《统计学习⽅法》第⼆版这本书的笔记,其实也就是我⾃⼰认为⽐较重要或者有⽤的内容,以及部分python 代码的实现。
由于博主能⼒有限,博⽂中提及的信息,也难免会有疏漏之处。希望发现疏漏的朋友能热⼼指出其中的错误,以便下次修改时能以⼀个更完美更严谨的样⼦,呈现在⼤家⾯前。同时如果有更好的⽅法也请不吝赐教。
如果有什么相关的问题,也可以关注评论留下⾃⼰的问题,我会尽量及时发送!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论