Yu-shui


  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 日程表

  • 搜索

KNN算法原理及代码实现

发表于 2019-04-14
字数统计: | 阅读时长 ≈

k邻近算法的原理和使用

1.算法原理

1. KNN算法三要素

KNN算法我们主要要考虑三个重要的要素,对于固定的训练集,只要这三点确定了,算法的预测方式也就决定了。这三个最终的要素是k值的选取,距离度量的方式和分类决策规则。

  1. 对于分类决策规则,一般都是使用前面提到的多数表决法。所以我们重点是关注与k值的选择和距离的度量方式。
  1. 对于k值的选择,没有一个固定的经验,一般根据样本的分布,选择一个较小的值,可以通过交叉验证选择一个合适的k值。
  • 选择较小的k值,就相当于用较小的领域中的训练实例进行预测,训练误差会减小,只有与输入实例较近或相似的训练实例才会对预测结果起作用,与此同时带来的问题是泛化误差会增大,换句话说,K值的减小就意味着整体模型变得复杂,容易发生过拟合;
  • 选择较大的k值,就相当于用较大领域中的训练实例进行预测,其优点是可以减少泛化误差,但缺点是训练误差会增大。这时候,与输入实例较远(不相似的)训练实例也会对预测器作用,使预测发生错误,且K值的增大就意味着整体的模型变得简单。
  • 一个极端是k等于样本数m,则完全没有分类,此时无论输入实例是什么,都只是简单的预测它属于在训练实例中最多的类,模型过于简单。
  1. 对于距离的度量,我们有很多的距离度量方式,但是最常用的是欧式距离。
2.核心思想

计算待标记的数据样本和数据集中的每个样本的距离,取距离最近的K个样本,待标记的数据样本就由这k个距离最近的样本投票产生

算法原理的伪代码

  • 遍历x_train中的所有样本,计算每个样本与X_test的距离,并吧距离保存在Distance数组中
  • 对Distance数组进行排序,取距离最近的k个点,即为X_knn
  • 对X-knn中统计每个类别的个数,即在class0在X_knn中有几个样本,class1在X_knn中有几个样本…..
  • 待标记的样本类别,就是在X_knn中样本个数最多的那个类别。
3.算法优缺点
  • 优点:准确性高,对异常值和噪声有较高的容忍度
  • 缺点:计算量大,对内存需求大

    2.简单运用(使用k邻近算法进行分类)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    from sklearn.datasets.samples_generator import make_blobs
    from matplotlib import pyplot as plt
    import numpy as np
    #生成数据

    centers=[[-2,2],[2,2],[0,4]]
    X,y=make_blobs(n_samples=600,centers=centers,random_state=0,cluster_std=0.6)

    #画出数据
    plt.figure(figsize=(16,10),dpi=144)
    c=np.array(centers)
    plt.scatter(X[:,0],X[:,1],cmap='cool',c=y,s=100)
    plt.scatter(c[:,0],c[:,1],s=100,marker='^',c='orange')

    #调用训练器来进行分类
    from sklearn.neighbors import KNeighborsClassifier
    k=5
    #训练模型
    clf=KNeighborsClassifier()
    clf.fit(X,y)

    #预测
    X_sample=[[0,2]]
    y_sample=clf.predict(X_sample)
    neighbors=clf.kneighbors(X_sample,return_distance=False)

    #画出该点和临近点
    print(X_sample)
    print(neighbors)
    print(X_sample[0][0])
    plt.scatter(X_sample[0][0],X_sample[0][1],c="red",s=100)

    for i in neighbors[0]:
    #print(X[i][0])
    plt.plot([X[i][0],X_sample[0][0]],[X[i][1],X_sample[0][1]],'k--',linewidth=0.8);

3.示例运用(使用k邻近算法进行回归拟合)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#生成数据集
import numpy as np
n_dots=400
X=5*np.random.rand(n_dots,1)
y=np.cos(X).ravel()#将多为数组将为一维
#print(X)
print("******************")
#print(y)

#添加一些噪声
y=y+0.2*np.random.rand(n_dots)-0.1

#训练模型
from sklearn.neighbors import KNeighborsRegressor
k=5
knn=KNeighborsRegressor(k)
knn.fit(X,y)

#将所有的预测点用吸纳画起来,形成回归曲线
T=np.linspace(0,5,500)[:,np.newaxis]#np.newaxis 在使用和功能上等价于 None,其实就是 None 的一个别名.
print(T.shape)
y_pred=knn.predict(T)
print("得分为{0}".format(knn.score(X,y)))

#画出拟合曲线
from matplotlib import pyplot as plt
plt.figure(figsize=(16,10),dpi=144)
plt.scatter(X,y,c='g',label='data',s=100)#画出训练样本
plt.plot(T,y_pred,c='k',label='prediction',lw=4)#画出拟合曲线(T为横坐标,y_pred为纵坐标
plt.axis('tight')
plt.title("KNeightborsRessor")
plt.show()

4.实际运用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
![gg](C:\Users\wuxun\Desktop\gg.PNG)from sklearn import datasets
import numpy as np
from sklearn.model_selection import train_test_split

text=datasets.load_iris()
#print(text)
target=text.target
data=text.data
#print(target)
print("***********")
#print(data)

data.shape
#将样本分为训练集和测试集
X_train,X_test,Y_train,Y_test=train_test_split(data,target,test_size=0.2)

#通过使用普通的k-均值算法,带权重的k-均值算法,指定半斤的k-均值算法对数据进行拟合
from sklearn.neighbors import KNeighborsClassifier,RadiusNeighborsClassifier

#构造三个模型

models=[]
models.append(("KNN",KNeighborsClassifier(n_neighbors=2)))
models.append(("KNN with weight",KNeighborsClassifier(n_neighbors2,weightsh="distance")))
models.append(("Radius Neighbors",RadiusNeighborsClassifier(n_neighbors=2,radius=500.0)))

#分别训练三个模型
results=[]
for name,model in models:
model.fit(X_train,Y_train)
results.append((name,model.score(X_test,Y_test)))
for i in range(len(results)):
print("name: {}: score:{}".format(results[i][0],results[i][1]))

#由于随机测验数据存在的差异,所以我们用KFold计算一般的算法性质
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
results=[]
for name,model in models:
kfold=KFold(n_splits=10)#将数据集分成十份,一份作为验证集
cv_result=cross_val_score(model,data,target,cv=kfold)#函数计算出十次数据集组合而得的模型得分
for i in range(len(results)):
print("name {} :scor {}".format(results[i][0],results[i][1].mean()))

#模型训练及分析
#普通的knn训练模型可能更优,我们使用普通的knn模型训练数据

knn=KNeighborsClassifier(n_neighbors=2)
knn.fit(X_train,Y_train)
train_score=knn.score(X_train,Y_train)
test_score=knn.score(X_test,Y_test)
print("tsin score:{},test score:{}".format(train_score,test_score))

from sklearn.model_selection import ShuffleSplit
#from common.utils import plot_learning_curve

#knn.KNeighborsClassifier(n_neighbors=2)
#cv=ShuffleSplit(n_splits=10,test_size=0.2,random_state=0)

from sklearn.feature_selection import SelectKBest#选择相关性最大的两个特征

selector=SelectKBest(k=2)
X_new=selector.fit_transform(data,target)
X_new[0:5]

#选择最好的两个特征在对三个模型进行检测
results=[]
for name,model in models:
kfold=KFold(n_splits=10)
cv_result=cross_val_score(model,X_new,target,cv=kfold)
results.append((name,cv_result))
for i in range(len(results)):
print("name:{}; cross val score:{}".format(results[i][0],results[i][1].mean()))


#画出二维数据
from matplotlib import pyplot as plt
plt.figure(figsize=(10,6),dpi=200)
plt.ylabel("BMI")
plt.xlabel("Glucose")
plt.scatter(X_new[:,0],X_new[:,1],c=target)
#plt.scatter(X_new,target,c='r',s=20,marker='o')

tensorflow 及机器学习基础知识

发表于 2019-04-09
字数统计: | 阅读时长 ≈

1.召回率和查全率

召回率(Recall Rate,也叫查全率,是检索出的相关文档数和文档库中所有的相关文档数的比率,衡量的是检索系统的查全率,精度是检索出的相关文档数与检索出的文档总数的比率,衡量的是检索系统查准率。

召回率(Recall)和精度(Precise)是广泛用于信息检索和统计学分类领域的两个度量值,用来评价结果的质量。

1.ROC曲线

1、roc曲线:接收者操作特征(receiveroperating characteristic),roc曲线上每个点反映着对同一信号刺激的感受性。

横轴:负正类率(false postive rate FPR)特异度,划分实例中所有负例占所有负例的比例;(1-Specificity)

纵轴:真正类率(true postive rate TPR)灵敏度,Sensitivity(正类覆盖率)

机器学习中常用的指标量

TP:正确的肯定数目

FN:漏报,没有找到正确匹配的数目

FP:误报,没有的匹配不正确

TN:正确拒绝的非匹配数目

由上表可得出横,纵轴的计算公式:

(1)真正类率(True Postive Rate)TPR: TP/(TP+FN),代表分类器预测的正类中实际正实例占所有正实例的比例。Sensitivity

(2)负正类率(False Postive Rate)FPR: FP/(FP+TN),代表分类器预测的正类中实际负实例占所有负实例的比例。1-Specificity

(3)真负类率(True Negative Rate)TNR: TN/(FP+TN),代表分类器预测的负类中实际负实例占所有负实例的比例,TNR=1-FPR。Specificity

AUC(Area under Curve):Roc曲线下的面积,介于0.1和1之间。Auc作为数值可以直观的评价分类器的好坏,值越大越好。

首先AUC值是一个概率值,当你随机挑选一个正样本以及负样本,当前的分类算法根据计算得到的Score值将这个正样本排在负样本前面的概率就是AUC值,AUC值越大,当前分类算法越有可能将正样本排在负样本前面,从而能够更好地分类。

3. 为什么使用Roc 和Auc评价分类器

既然已经这么多标准,为什么还要使用ROC和AUC呢?因为ROC曲线有个很好的特性:当测试集中的正负样本的分布变换的时候,ROC曲线能够保持不变。在实际的数据集中经常会出现样本类不平衡,即正负样本比例差距较大,而且测试数据中的正负样本也可能随着时间变化。

4.PR曲线

P-R曲线刻画查准率和查全率之间的关系,查准率指的是在所有预测为正例的数据中,真正例所占的比例,查全率是指预测为真正例的数据占所有正例数据的比例。
即:查准率P=TP/(TP + FP) 查全率=TP/(TP+FN)
查准率和查全率是一对矛盾的度量,一般来说,查准率高时,查全率往往偏低,查全率高时,查准率往往偏低,例如,若希望将好瓜尽可能多选出来,则可通过增加选瓜的数量来实现,如果希望将所有的西瓜都选上,那么所有的好瓜必然都被选上了,但这样查准率就会较低;若希望选出的瓜中好瓜比例尽可能高,则可只挑选最有把握的瓜,但这样就难免会漏掉不少好瓜,使得查全率较低。

在很多情况下,我们可以根据学习器的预测结果对样例进行排序,排在前面的是学习器认为最可能是正例的样本,排在后面的是学习器认为最不可能是正例的样本,按此顺序逐个把样本作为正例进行预测,则每次可计算当前的查全率和查准率,以查准率为y轴,以查全率为x轴,可以画出下面的P-R曲线。

PR曲线

5.IMDB影评数据集

该数据下载后包含train和test两个文件夹和三个文件,其中test文件夹中的两个文件夹pos和neg分别为1.25W个代表积极和消极态度的训练样本。而train中的三个文件夹pos、neg、unsup分别为1.25W代表积极和消极态度的训练样本以及5W个未标记的样本。未标记样本可以用来作无监督学习时使用。

THUCnews数据集

THUCNews是根据新浪新闻RSS订阅频道2005~2011年间的历史数据筛选过滤生成,包含74万篇新闻文档(2.19 GB),均为UTF-8纯文本格式。我们在原始新浪新闻分类体系的基础上,重新整合划分出14个候选分类类别:财经、彩票、房产、股票、家居、教育、科技、社会、时尚、时政、体育、星座、游戏、娱乐

用skikit-learn实现决策树

发表于 2019-04-07
字数统计: | 阅读时长 ≈

用scikit-learn实现决策树算法

1、scikit-learn决策树算法类库介绍

​ scikit-learn决策树算法类库内部实现是使用了调优过的CART树算法,既可以做分类,又可以做回归。分类决策树的类对应的是DecisionTreeClassifier,而回归决策树的类对应的是DecisionTreeRegressor。两者的参数定义几乎完全相同,但是意义不全相同。下面就对DecisionTreeClassifier和DecisionTreeRegressor的重要参数做一个总结,重点比较两者参数使用的不同点和调参的注意点。

2、DecisionTreeClassifier和DecisionTreeClassifier 重要参数调参注意点

2.1 特征选择标准criterion

​ DecisionTreeClassifier:可以使用”gini”或者”entropy”,前者代表基尼系数,后者代表信息增益。一般说使用默认的基尼系数”gini”就可以了,即CART算法。除非你更喜欢类似ID3, C4.5的最优特征选择方法。

​ DecisionTreeRegressor:可以使用”mse”或者”mae”,前者是均方差,后者是和均值之差的绝对值之和。推荐使用默认的”mse”。一般来说”mse”比”mae”更加精确。除非你想比较二个参数的效果的不同之处。

2.2 特征划分点选择标准splitter

​ 可以使用”best”或者”random”。前者在特征的所有划分点中找出最优的划分点。后者是随机的在部分划分点中找局部最优的划分点。
​ 默认的”best”适合样本量不大的时候,而如果样本数据量非常大,此时决策树构建推荐”random”

2.3 划分时考虑的最大特征数max_features

​ 可以使用很多种类型的值,默认是”None”,意味着划分时考虑所有的特征数;如果是”log2”意味着划分时最多考虑log2N个特征;如果是”sqrt”或者”auto”意味着划分时最多考虑sqrt(N)个特征。如果是整数,代表考虑的特征绝对数。如果是浮点数,代表考虑特征百分比,即考虑(百分比xN)取整后的特征数。其中N为样本总特征数。
​ 一般来说,如果样本特征数不多,比如小于50,我们用默认的”None”就可以了,如果特征数非常多,我们可以灵活使用刚才描述的其他取值来控制划分时考虑的最大特征数,以控制决策树的生成时间。

2.4 决策树最大深max_depth

​ 决策树的最大深度,默认可以不输入,如果不输入的话,决策树在建立子树的时候不会限制子树的深度。一般来说,数据少或者特征少的时候可以不管这个值。如果模型样本量多,特征也多的情况下,推荐限制这个最大深度,具体的取值取决于数据的分布。常用的可以取值10-100之间。

2.5 内部节点再划分所需最小样本数min_samples_split

​ 这个值限制了子树继续划分的条件,如果某节点的样本数少于min_samples_split,则不会继续再尝试选择最优特征来进行划分。 默认是2.如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。我之前的一个项目例子,有大概10万样本,建立决策树时,我选择了min_samples_split=10。可以作为参考。

2.6 叶子节点最少样本数min_samples_leaf

​ 这个值限制了叶子节点最少的样本数,如果某叶子节点数目小于样本数,则会和兄弟节点一起被剪枝。 默认是1,可以输入最少的样本数的整数,或者最少样本数占样本总数的百分比。如果样本量不大,不需要管这个值。如果样本量数量级非常大,则推荐增大这个值。之前的10万样本项目使用min_samples_leaf的值为5,仅供参考。

2.7 叶子节点最小的样本权重和min_weight_fraction_leaf

​ 这个值限制了叶子节点所有样本权重和的最小值,如果小于这个值,则会和兄弟节点一起被剪枝。 默认是0,就是不考虑权重问题。一般来说,如果我们有较多样本有缺失值,或者分类树样本的分布类别偏差很大,就会引入样本权重,这时我们就要注意这个值了。

2.8 最大叶子节点数max_leaf_nodes

​ 通过限制最大叶子节点数,可以防止过拟合,默认是”None”,即不限制最大的叶子节点数。如果加了限制,算法会建立在最大叶子节点数内最优的决策树。如果特征不多,可以不考虑这个值,但是如果特征分成多的话,可以加以限制,具体的值可以通过交叉验证得到。

2.9 类别权重class_weight

​ 不适用于回归树。指定样本各类别的的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策树过于偏向这些类别。这里可以自己指定各个样本的权重,或者用“balanced”,如果使用“balanced”,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。当然,如果你的样本类别分布没有明显的偏倚,则可以不管这个参数,选择默认的”None”

2.10 节点划分最小不纯度min_impurity_split

​ 这个值限制了决策树的增长,如果某节点的不纯度(基尼系数,信息增益,均方差,绝对差)小于这个阈值,则该节点不再生成子节点。即为叶子节点 。

2.11 数据是否预排序presort

​ 这个值是布尔值,默认是False不排序。一般来说,如果样本量少或者限制了一个深度很小的决策树,设置为true可以让划分点选择更加快,决策树建立的更加快。如果样本量太大的话,反而没有什么好处。问题是样本量少的时候,我速度本来就不慢。所以这个值一般懒得理它就可以了。

​ 除了这些参数要注意以外,其他在调参时的注意点有:
  1)当样本少数量但是样本特征非常多的时候,决策树很容易过拟合,一般来说,样本数比特征数多一些会比较容易建立健壮的模型
  2)如果样本数量少但是样本特征非常多,在拟合决策树模型前,推荐先做维度规约,比如主成分分析(PCA),特征选择(Losso)或者独立成分分析(ICA)。这样特征的维度会大大减小。再来拟合决策树模型效果会好。
​  3)推荐多用决策树的可视化(下节会讲),同时先限制决策树的深度(比如最多3层),这样可以先观察下生成的决策树里数据的初步拟合情况,然后再决定是否要增加深度。
  4)在训练模型前,注意观察样本的类别情况(主要指分类树),如果类别分布非常不均匀,就要考虑用class_weight来限制模型过于偏向样本多的类别。
  5)决策树的数组使用的是numpy的float32类型,如果训练数据不是这样的格式,算法会先做copy再运行。
  6)如果输入的样本矩阵是稀疏的,推荐在拟合前调用csc_matrix稀疏化,在预测前调用csr_matrix稀疏化

安装时遇到的问题

发表于 2019-04-07
字数统计: | 阅读时长 ≈

配置 python 和 anaconda 环境,在装 jupyter notebook 时,出了点问题,搞了一天半终于搞好了,也是在 github 里找到了这个问题的解答。

当时显示的是无法连接到python,不知道为什么,帮他们装的notebook居然都是中文,后来发现是 no connection to kernel

具体操作

1
pip install tornado==4.5.3

这么一个错误花了一天多。。服了。。

很明显,这是版本问题,现在直接 pip install jupyter notebook 时,附带安装的 tornado 是6.0版本的,而能操作的是4.5.3版本的(掀桌)。。。

tensorflow-gpu配置

发表于 2019-04-07
字数统计: | 阅读时长 ≈

引言

越来越多的的人入坑机器学习,深度学习,tensorflow 作为目前十分流行又强大的一个框架,自然会有越来越多的新人(我也刚入门)准备使用,一般装的都是 CPU 版的 tensorflow,然而使用 GPU 跑 tensorflow,速度可以快上好几倍。正好前段时间看到了使用小米pro(我目前使用的笔记本,感觉贼好用(我没有在推销))配置 gpu 的教程,就试了试,最后成功了。

环境

操作系统:Windows10

配置:Tensorflow 1.12 + CUDA 9.0 +cuDNN v7.1 for CUDA9.0

GPU:NVIDIA GeForce MX150(小米pro i7-8550 8G 256G)

软件:Anaconda

注:发现 tensorflow 1.13 发布了,但其配置要求与1.12版本有所差别,若按照本博客配置1.13版本运行会报错(可能与cuda版本相关,据说1.13版本支持cuda10了,可以试试cuda10)。 2019/3/2

实际操作

一、安装CUDA、cuDNN

CUDA

关于 CUDA 的安装,看这篇文章,写的很详细(好吧,还是我比较懒,不太想敲键盘)

cuDNN

官网下载地址

注意:下载的时候要下对应自己下载的CUDA的版本

把下载好的 cuDNN 的 zip 解压后,把 bin、include、lib 三个文件夹内的文件拷贝到 CUDA 9.0 的目录下的对应文件中即可。

CUDA 的默认路径

1
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\

然后开始配置环境变量

1
2
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\lib\x64
C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0

二、创建虚拟环境

这里还是比较建议新创建一个虚拟环境,免得安装好的 tensorflow-gpu 跟原环境中的某些包冲突。

1.打开Anaconda Prompt

img

2.创建虚拟环境

键入

1
conda create --name tensorflow-gpu python=3.6.1

3.启动虚拟环境

1
activate tensorflow-gpu

img

三、安装tensorflow-gpu

1.安装

两种方法

  1. pip install –upgrade tensorflow-gpu

  2. 下载 tensorflow-gpu 的离线安装包,找到下载好的whl路径,然后键入

    1
    pip install c:\...\tensorflow_gpu-xxxx.whl

    下载地址

2.测试

输入

1
python

然后再输入

1
import tensorflow as tf

如果没报错,就表示安装成功了。

然后,再来段 tensorflow 的 hello world

复制代码;)

1
2
3
4
5
6
7
8
import tensorflow as tf
tf.enable_eager_execution()

a = tf.constant(1)
b = tf.constant(1)
c = tf.add(a, b)

print(c)

复制代码;)

img

总结

至此,我们的 tensorflow-gpu 就装好了,接下来就开始 tensorflow 的学习之旅吧。

机器学习5 决策树(部分)

发表于 2019-03-19
字数统计: | 阅读时长 ≈

​

机器学习5(决策树<1>)

1.决策树

决策树为树结构,节点时决策结果,每隔叶节点存放一个类别,在每个节点的数个输出中,每个输出都代表特征属性在某个值域上的输出。

2.构成

构造决策树最关键时在节点进行分支的时候,所分出的各个分支要尽可能的纯。典型的有三种算法:ID3算法使用信息增益作为不纯度,C4.5算法使用信息增益律作为不纯度,CART算法使用基尼系数作为不纯度。

3. 信息增益,信息增益率,基尼系数

信息增益越大,属性纯度越高,信息增益率是信息增益处以数目的平均值,基尼指数反应的是随机抽取两个样本,其类别不一致的概率,因此Gini(D)越小,数据集D的纯度越高。

4. 剪枝(防止过拟合)

优点:计算复杂度不高,输出结果容易理解,对中间值的缺失不敏感,可以处理不相关特征数据
缺点:可能产生过拟合问题
适用数据类型:数值型和标称型

3.1 预剪枝
预剪枝对划分前后的泛化性能进行估计,若对某一节点划分后验证集的精度下降,则禁止划分该节点。预剪枝使得决策树的很多分支没有展开,不仅降低了过拟合的风险,还显著减少了决策树的训练时间开销和测试时间开销。但另一方面,有些分支的当前划分虽不能提升泛化性能、甚至可能导致泛化性能暂时下降,但在其基础上进行的后续划分却有可能导致性能显著提高。预剪枝基于“贪心”的本质禁止这些分支展开,给预剪枝决策树带来了欠拟合的风险。
停止分类的条件:

(1) 如果节点中所有观测属于一类;
(2) 如果节点中所有观测的属性取值一致;
(3) 如果树的深度达到设定的阈值;
(4) 如果该节点所含观测值小于设定的父节点应含观测数的阈值;
(5) 如果该节点的子节点所含观测数将小于设定的阈值;
(6) 如果没有属性能满足设定的分裂准则的阈值。

3.2 后剪枝
后剪枝先从训练集生成一棵完整决策树,对每个节点,若将该节点对应的子树替换为叶节点后,验证集精度提升,则进行剪枝。后剪枝决策树通常比预剪枝决策树保留了更多的分支。一般情况下,后剪枝决策树的欠拟合风险很小,泛化性能往往优于预剪枝决策树,但后剪枝过程是在生成完全决策树之后进行的,并且要自底向上地对树中的所有非叶节点进行逐一考察,因此其训练时间开销比未剪枝决策树和预剪枝决策树都要大得多。
后剪枝的方法:

(1) Reduced-Error Pruning (REP):删除以此节点为根的子树使其成为叶节点,赋予该节点关联的训练数据的最常见分类,当修剪后的树对于验证集合的性能不会比原来的树差时,才真正删除该节点。
(2) Pessimistic Error Pruning (PEP):计算某节点的误差,计算该节点的叶节点误差之和,当其误差小于等于叶节点误差之和加一个标准差时,则修建该节点。
(3) CCP:给基尼指数加上惩罚项,此时树的层次越深,基尼指数的惩罚项越大。

应用实例

发表于 2019-03-18
字数统计: | 阅读时长 ≈

海量数据中的商品推荐

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
import numpy as np
from collections import defaultdict
from operator import itemgetter

dataset_filename="C:\Python数据挖掘入门与实践代码和数据集\Code_REWRITE\Chapter 1"
X=np.loadtxt(dataset_filename+r"\affinity_dataset.txt")
#print(X)
v=defaultdict(int)
i=defaultdict(int)
n=defaultdict(int)

for sample in X:
for permiss in range(4):
if sample[permiss]==0:
continue
n[permiss]+=1
for c in range(4):
if permiss==c:
continue
if sample[c]==1:
v[(permiss,c)]+=1#两者均为1时加一
else:
i[(permiss,c)]+=1#两者不同时为1

support=v
#permiss=1
#c=3
#print(" -Support:{0}".format(support[(permiss,c)]))
confidence=defaultdict(float)
'''
for permiss,c in v.keys():
rule=(permiss,c)
confidence[rule]=v[rule]/n[permiss]
print(confidence[rule])
'''
def print_rule(permiss,c,support,confidence,features):
permiss_name=features[permiss]
c_name=features[c]
print("Rule if a people buy {0} they will also buy {1}".format(permiss_name,c_name))

#s输出置信度
#输出支持度
print(" -Support: {0}".format(support[(permiss,c)]))
print(" -Confidence".format(confidence[(permiss,c)]))
##排序找出最佳规则

print(support)#内涵键值对
sorted_support=sorted(support.items(),key=itemgetter(1),reverse=True)
#输出支持度最高的五个规则
for index in range(5):
print(" Rule #{0}".format(index+1))
permiss,c=sorted_support[index][0]
print_rule(permiss,c,support,confidence,features)

#输出置信度最高的规则
sorted_confidence=sorted(support.items(),key=itemgetter(1),reverse=True)
for index in sorted_confidence:
permiss,c=sorted_confidence[index][0]
print_rule(permiss,c,support,confidence,features)

java聊天室的实现

发表于 2019-03-18
字数统计: | 阅读时长 ≈

java 聊天室的实现

1.部分代码

Sqlserver类是一个自己设定的数据存储类,与登录界面共同作用,记录当前在线的人数,以及实现一些必备的功能函数,如返回在线用户的列表,删除用户等。

projectcenter;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

//用户数据库
public class SqlServer {
private static Map<String,UserInfor>SQL=new HashMap();

//判断输入账号是否存在
public static boolean CheckUser(String name) {
if(SQL.containsKey(name)) {
return true;
}
//System.out.println("不存在此用户:"+name);
return false;
}

//检查账号密码是否输入正确
public static boolean CheckPassword(String name,String Password) {
if(SQL.get(name).Check(Password)) {
return true;
}else {
return false;
}
}

//返回对象数组
public static Map<String, UserInfor> Getusers() {
return SQL;
}



//返回key1值对应的对象
public UserInfor returnUser(String name) {
return SQL.get(name);
}




//返回用户姓名列表
public String[] Groupusername() {

Object[] key = SQL.keySet().toArray();
Arrays.sort(key);
int l=key.length;
String username[]=new String[l];


for(int i=0;i<key.length;i++) {
username[i]=key[i].toString();
//System.out.println(key[i].toString());
}


return username;
}

//创建用户
public int BuildNewUser(String name,String password) {
if(SQL.containsKey(name)) {
//System.out.println("该用户名已存在!请重新输入");
return 0;
}else {
UserInfor u=new UserInfor();
u.SetName(name);
u.SetPwd(password);
System.out.println("新用户密码为:"+password);
this.SQL.put(name,u);
return 1;
}

}


//遍历打印Map中的键值对
public static void ShowMap(){
for(Map.Entry<String, UserInfor> entry: SQL.entrySet()){
System.out.println(entry.getKey()+"="+entry.getValue().toString());
}
}

//删除用户
public static void DeleteUser(String name) {
SQL.get(name).SetOnline2();


}

//返回在线的用户id列表
public String[] WhoisOnline() {

Object[] key = SQL.keySet().toArray();
Arrays.sort(key);
int l=key.length;
String username[]=new String[l];
for(int i=0;i<key.length;i++) {
if(SQL.get(key[i].toString()).getOnline()) {//如果在线则加入数组
username[i]=key[i].toString();
}
}
return username;
}

//返回不在线用户列表
public String[] WHoisnotOnline() {
Object[] key = SQL.keySet().toArray();
Arrays.sort(key);
int l=key.length;
String username[]=new String[l];
for(int i=0;i<key.length;i++) {
if(!SQL.get(key[i].toString()).getOnline()) {//如果不在线则加入数组
username[i]=key[i].toString();
}
}
return username;
}

//系统先建立十个用户
static{
for (int i=0;i<10;i++) {
UserInfor u=new UserInfor();
u.SetName(String.valueOf(i+1));//用户名即是索引
u.SetPwd("123456");
SQL.put(u.get_name(),u);
}
}


}

接下来是用户界面类,与BuildCheck类相连接每当用户实现了登录窗口的检测,则新建一个用户类对象Client,用户类中包含了界面的实现和socket消息的发送和接受,以信息的开头辨别信息的种类,若为一号信息则是私聊信息,则再在BufferedReader中读取私聊信息并显示在私聊界面上,二号信息指代群信息。在界面设计时,应当有好友列表上下线下线的的刷新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

public class Client extends Thread{/部分代码

//监听事件的添加
send.addActionListener(new ActionListener() {//发送私聊消息

@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
WriterMess("1");//表示是私聊信息
WriterMess(selected);//私聊用户号
String mess=textfield.getText();
WriterMess(mess);//私聊信息
area.append("自己:"+mess+"\n");
if(mess.equals("bye")) {//设置用户下线
WriterMess("3");
}
}

});

send2.addActionListener(new ActionListener() {//实现群聊功能

@Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
try {
WriterMess("2");
String gets=textfield2.getText();
WriterMess(gets);
if(gets.equals("bye")) {//设置用户下线
WriterMess("3");
}
} catch(Exception e) {
e.printStackTrace();

}
}

});

//JList点击事件的添加
list1.addMouseListener(new MouseAdapter() {

@Override
public void mouseClicked(MouseEvent arg0) {
// TODO Auto-generated method stub
String select=(String) list1.getSelectedValue();
if(!select.equals(userinfor.get_name())) {//不能对自己进行私聊
area.append(" ================================================\n");
area.append(" ===你选择"+select+"号在线客户进行私聊===\n");

selected=select;

}else {
area.append(" ============您不能选择自己进行私聊!===========\n");
}
}

});

list2.addMouseListener(new MouseAdapter() {

@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
area.append("=================当前用户不在线!=============\n");
}


});

}


public void ShashSelf() {
this.use.updateUI();
}


public void CloseSelf() {//将自己关闭
try {
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

public void ReadMess() {
//读取服务器返回的消息
try {
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String mess1 = br.readLine();
while(true) {

//私聊消息

System.out.println("mess1:"+mess1);
System.out.println("****************************************");




/*while(mess1.equals("4")) {//刷新
this.use.revalidate();
mess1=br.readLine();
System.out.println("mess1:"+mess1);
System.out.println("****************************************");
}*/


while(mess1.equals("1")) {//私聊
System.out.println("*********收到信息**************\n");
String mess2=br.readLine();//用户号
System.out.println("发信息的用户号为"+mess2);
String mess3=br.readLine();//信息
System.out.println("私信为"+mess3);
area.append("客户"+mess2+"对您私聊说: ");
area.append(mess3+"\n");

mess1=br.readLine();//刷新mess1
System.out.println("mess1:"+mess1);
System.out.println("****************************************");
}

//群聊消息
while((mess1.equals("2"))) {
String mess2=br.readLine();
if(mess2.equals("4")) {
//this.use.revalidate();
//use.repaint();
String WhoisOnline[]=SQL.WhoisOnline();
list1.setListData(WhoisOnline);
String WhoisNotOnline[]=SQL.WHoisnotOnline();
list2.setListData(WhoisNotOnline);
System.out.println("2中收到四号消息");
mess1=br.readLine();
}else {
area2.append(mess2+"\n");
mess1=br.readLine();
System.out.println("mess1:"+mess1);
System.out.println("****************************************");
}
}

while((mess1.equals("3"))) {//终止
br.close();
bw.close();
in.close();
out.close();
this.socket.close();
mess1="";
this.runnning=false;
SqlServer.DeleteUser(this.userinfor.get_name());
}

if(!this.runnning) {
break;
}
}

}catch(Exception e) {
e.printStackTrace();
}
}



}


}

自定义一个ChatList类,用于管理在线聊天的与服务器相连的线程对象,在这个类中实现了向所有的在线Client发送消息的函数功能,也实现了删除在线ThreadForChat对象,在线的ThreadForChat是一个与Server服务器相关联的类,每当有一个Client与Server相连接,Server就创造一个ThreadForChat对象与之相连实现通信,在Server类中的强制删除功能既是删除对应的ThreadForChat类并向对应的Client对象发出下线的消息,实现强制下线。CLass BuildCheck是登录窗口,每当用户输入账号和验证密码并且检验正确时,就new一个Client对象。

机器学习3

发表于 2019-03-10
字数统计: | 阅读时长 ≈

机器学习3( matplotlib补充以及线性回归之最小二乘法的实现)

1.matplotlib补充
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import numpy as np
import matplotlib as mp
from pylab import *

figure(figsize=(16,6),dpi=80)
subplot(1,1,1)
#创建等差数列
X=np.linspace(-np.pi,np.pi,256,endpoint=True)
c,s=np.cos(X),np.sin(X)
#绘制余弦曲线
plot(X,c,color="blue",linewidth=1.0,linestyle="-")
#绘制正弦曲线
plot(X,s,color="green",linewidth=1.0,linestyle="-")
xlim(-4.0,4.0)
#设置上下限,设置横轴标记符
xticks(np.linspace(-4,4,9,endpoint=True))
ylim(-1.0,1.0)
yticks(np.linspace(-1,1,5,endpoint=True))

#设置边界
xlim(X.min()*(1.1),X.max()*1.1)
ylim(c.min()*1.1,c.max()*1.1)

#设置记号
xticks([-np.pi,-np.pi/2,0,np.pi/2,np.pi],[r'$-\pi$',r'$-\pi/2$',r'$0$',r'$+\pi/2$',r'$+\pi$'])
yticks([-1,0,+1],[r'$-1$',r'$-\pi/2$',r'$0$',r'$+\pi/2$',r'$+\pi$'])



savefig("exciese1",dpi=72)
2.线性回归之最小二乘法(使用sklearn中的糖尿病数据集)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets,linear_model
from sklearn.metrics import mean_squared_error,r2_score

#加载数据集
diabetes=datasets.load_diabetes()
diabetes_X=diabetes.data[:,np.newaxis,2]

diabetes_x_train=diabetes_X[:-20]
diabetes_x_test=diabetes_X[-20:]

diabetes_y_train=diabetes.target[:-20]
diabetes_y_test=diabetes.target[-20:]


regr=linear_model.LinearRegression()
regr.fit(diabetes_x_train,diabetes_y_train)

diabetes_y_predict=regr.predict(diabetes_x_test)

#系数
print(regr.coef_)
#均方差
print("%.2f"%mean_squared_error(diabetes_y_test,diabetes_y_predict))
#预测
print("得分:%.2f"%r2_score(diabetes_y_test,diabetes_y_predict))

#绘制结果
plt.scatter(diabetes_x_test,diabetes_y_test,color='black')
plt.plot(diabetes_x_test,diabetes_y_predict,color='blue',linewidth=3)
plt.xticks()
plt.yticks()
plt

运行结果

补充:matplotlib

发表于 2019-03-09
字数统计: | 阅读时长 ≈

机器学习2(补充:Matplotlib)

matplotlib及其子包PyPlot时实现可视化二维数据的基本工具,PyPlot的核心时plot方法,实现为传入一个列表或者一维数组,只要传入一个参数,就会假设该值为y值序列,并自动生成x值。可以接受指明线条属性的参数。

示例代码:

1
2
3
4
5
6
7
import numpy as np
import matplotlib.pyplot as plt

x=np.arange(0.,5.,0.2)
plt.plot(x,x**4,'r',x,x*90,'bs',x,x**3,'g^')
plt.show()
print(help(plt.plot))

图形显示结果如下:

程序运行结果

也可以使用help(plt.plot)获得完整的线条风格列表,截取一部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
Parameters
----------
x, y : array-like or scalar
The horizontal / vertical coordinates of the data points.
*x* values are optional. If not given, they default to
``[0, ..., N-1]``.

Commonly, these parameters are arrays of length N. However,
scalars are supported as well (equivalent to an array with
constant value).

The parameters can also be 2-dimensional. Then, the columns
represent separate data sets.

创建多个坐标轴,使用subplot命令

1…345

Yu-shui

46 日志
GitHub
© 2019 Yu-shui | Site words total count:
由 Hexo 强力驱动
|
主题 — NexT.Pisces v5.1.4