MinMaxScaler in sklearn

  • sklearn中的特征缩放
➜ test ✗ cat MinMaxScaler.py
# 导入MinMaxScaler
from sklearn.preprocessing import MinMaxScaler

# 使用numpy存储数据
import numpy

# 将权重以浮点数形式存储在numpy.array中, 如若此处为整数, fit_transform时会报错
weights = numpy.array([[115.], [140.], [175.]])

# 生成MinMaxScaler对象
scaler = MinMaxScaler()

# 使用fit_transform()计算特征缩放后的权重
rescaler_weights = scaler.fit_transform(weights)

# 结果输出
print(rescaler_weights)

执行结果:

➜ test ✗ python3 MinMaxScaler.py
[[0.        ]
 [0.41666667]
 [1.        ]]

Decision Tree (三)

写在前面

在这章内容中, 将重点探讨决策树的表述方式, ID3, 以及如何处理连续属性, 何时停止等问题.

分类与回归

Classification(分类): 将输入的值映射到离散值.
Regression(回归): 从某种输入空间映射到某个实际数字.

分类学习

  • Instance(实例): 输入集, 可以是相片, 评分等数据.
  • Concept(概念): 函数, 将输入映射到输出, 提取实例信息, 将实例映射到某类输出(True|False).
  • Target Concept(目标概念): 实际答案.
  • Hyprhesis(假设): 所有概念的集合, 所有可能的函数.
  • Sample(样本): 训练集.
  • Candindate(候选者): 一个你认可可能会是目标概念的概念.
  • Testing Set(测试集): 测试集.

决策树学习

  • 挑选最佳属性.
  • 提出一个相关问题.
  • 沿着答案的路径.
  • 然后继续挑选最佳属性, 反复以上步骤, 直至可能性空间缩小到只有一个答案的时候停止.

可表达性

AND

如图, 决策树可以通过两个节点表述A AND B的计算过程与结果.

OR

如图, 决策树可以通过两个节点表述A OR B的计算过程与结果.

XOR

如图, 决策树可以通过两个节点表述A XOR B的计算过程与结果.

ID3算法

  • 选取A作为最优属性分割数据
  • 分配A作为节点的决策属性
  • 为A的每个值创建一个决策节点
  • 将训练实例分类到叶子
  • 如果训练集完美分类则停止, 否则继续迭代

ID3偏差

  • Restriction Bias(限定偏差): Hyprhesis(假设)集合, 决策树以及它可以表述的内容, 而不会去考虑一元二次函数以及无穷函数等, 只考虑决策树中所给出的离散变量所表示的可能情况.
  • Reference Bias(优选偏差): 它会告诉我们首选的假设集合的来源.
  • 归纳偏差: ID3算法的归纳偏差来自它的搜索策略, 该策略假定某种假设胜于其它假设, 较短的假设比较长的假设要更优, 因此称这种归纳偏差为优选偏差或搜索偏差. 相反, 候选消除算法的偏差是对待考虑假设的一种限定, 这种形式的偏差通常称为限定偏差或语言偏差. 通常, 优选偏置比限定偏置更符合需要. 因为它保证了位置的目标函数被包含在学习器工作的假设空间中(要不然很可能白忙活一场). 但在实际中, 综合使用两者的学习系统是很常见的(例如使用最小均方差(优选偏置)的以线性函数(限定偏置)来表示评估函数的问题).

处理连续属性

使用决策树处理决策属性时, 可以采用范围判断的方式.(注意有效的范围选取)
例如: 年龄可以分为>=20|<20两部分, 这样就可以对一些连续的数值进行处理, 例如输入18.5, 则被归类到<20这部分.

什么时候停止

  • 内容被正确归类时.(如果有多个对象相同, 实例相同, 但标签不同的样本, 则会陷入死循环.)
  • 属性耗尽时.(对于连续属性的处理不好)
  • 注意overfit(过拟合).(根据交叉验证和测试集来检查决策树)
  • 剪枝.(会出现误差)

写在最后

到这里, 对决策树的概念及算法已经有了大致的认识. 接下来还会陆续更新一些细节相关的内容.

Decision Tree (二)

写在前面

在这个章节里面, 我们将会更深入的研究决策树.

贪心算法

贪心算法|贪婪算法: 在对问题求解时, 总是做出在当前看来是最好的选择. 也就是说, 不从整体最优上加以考虑, 他所做出的是在某种意义上的局部最优解. 而我们现在所研究的决策树, 也是一种贪心算法.

奥卡姆剃刀

奥卡姆剃刀: 切勿浪费较多东西, 去做'用较少的东西, 同样可以做好的事情'. 简单点说, 便是: be simple.

可线性分离的数据

如下图, 假设我们的朋友Tom喜欢冲浪, 但是冲浪需要满足两个条件, 要有风, 要有太阳, 图中坐标中横轴表示风的大小, 纵轴表示太阳的大小, 他不会在天气不够晴朗的时候去冲浪, 也不会在风力较弱的时候去冲浪, 他只会在有风并且天晴的时候去冲浪. 图中'x'表示不会冲浪, 'o'表示会冲浪. 那么, 结合下图, 这些数据是线性可分的吗?

显然, 这些数据是不能被线性分割的, 因为我们无法在这个空间中找到可以分割这些数据的直线.

多元线性问题

对于这个问题的研究, 我们可以先问, 有没有风, 我们可以在横轴上设定一个阈值, 这个阈值设定了一个决策面, 当数据的横轴值在这个点右边时, 则判断为有风, 左边为无风. 可以发现, 两个结果中, 已经有一个代表了最终的分类结果, 那就是左边那一部分, 当没有风的时候, Tom不会去冲浪. 然而在有风的情况下, 我们则需要考虑天气是否晴朗的问题.

这里, 我们可以在纵轴上也设定一个阈值, 这个阈值决定了是否天晴.
如果天气不晴朗, 那就会得到'x', 也就是不能冲浪.
如果天气晴朗, 会得到'o', 可以冲浪.
最终, 我们得到以下决策树:

代码实现

关于代码实现与sklearn的使用, 请参照另外一篇博文DecisionTree Classifier.
在使用DecisionTreeClassifier()训练数据时, 可以使用sklearn.metrics中的accuracy_score()函数来对数据准确性进行评分.

Entropy(熵)

定义: 熵是一系列样本中的不纯度的测量值.
关于熵的定义与计算方法, 请参照另外一篇博文Entropy.
在使用决策树对数据分割时, 要尽可能减少杂质, 熵的值越小越好.

Information Gain(信息增益)

关于信息增益的定义与计算方法, 请参照另外一篇博文Information Gain.
在决策树中, 算法会最大化信息增益.

决策树的优缺点

优点: 易于使用, 结构清晰, 能够以图形化方式很好的剖析数据, 结果清晰容易理解.
缺点: 容易overfit(过拟合), 需要谨慎调参.

写在最后

在这章内容中, 我们重点讨论了决策树是如何对数据进行分割, 以及熵与信息增益的计算过程, 以及它的优缺点所在.
在下一章中, 我们将重点讨论决策树的可表达性与ID3算法.

Decision Tree (一)

写在前面

在这篇文章里面, 我们介绍下决策树的一些基本知识.

举个例子

下表为AppStore中下载软件的用户信息(性别, 年龄)与下载的App名称(PS. 当然, 这些只是我们为了学习伪造的数据.)

Gender Age App
F 15 PockmonGo
F 25 WhatsApp
M 32 SnapChat
F 40 WhatsApp
M 12 PockmonGo
M 14 PockmonGo

问: 分析图一中的数据, 分析性别和年龄哪个特征对预测用户会下载哪个app更有效?
[A] 性别
[B] 年龄

分析

按照性别划分

Gender Age App
F 15 PockmonGo
F 25 WhatsApp
M 32 SnapChat
F 40 WhatsApp
M 12 PockmonGo
M 14 PockmonGo

如果按照性别划分, Fmale(标红的部分)中出现了PockmonGo与WhatsApp, Male(标蓝的部分)中出现了SnapChat与PockmonGo, 并未能将数据很好的分割开来.

按照年龄划分

Gender Age App
F 15 PockmonGo
F 25 WhatsApp
M 32 SnapChat
F 40 WhatsApp
M 12 PockmonGo
M 14 PockmonGo

如果按照年龄划分, 年龄<20(标红的部分)中只出现了PockmonGo, 年龄>=20(标蓝的部分)中出现了WhatsApp与SnapChat, 对数据的分割效果较好.

得出结论

很明显, 经过思考, 上面这道题应该选择[B] 年龄.

最终的分类

Gender Age App
F 15 PockmonGo
F 25 WhatsApp
M 32 SnapChat
F 40 WhatsApp
M 12 PockmonGo
M 14 PockmonGo

首先, 我们按照年龄段(<20|>=20)将PockmonGo的用户给分割出来. 然后, 剩下的数据里面, 通过性别(M|F)将WhatsApp与SnapChat的用户分割出来, 得出最终的结果.

树状结构表述

这样我们就得到了一个决策树. 当有新用户访问AppStore时, 我们可以先根据年龄段划分, 如果年龄<20, 则推荐PockmonGo; 如果年龄>=20, 则根据其性别推荐, 如若为男性, 则推荐SnapChat, 女性则推荐WhatsApp.

写在后面

在本文中, 我们已经了解决策树的一些基本原理, 在下一篇文章中, 我们将更深入的探讨决策树.

Grid Search in sklearn

➜ test ✗ cat gridSearchCV.py
import numpy as np
from sklearn import cross_validation
from sklearn import datasets
from sklearn import svm
from sklearn import grid_search

# 使用iris数据集
iris = datasets.load_iris()
print(iris.data.shape)
print(iris.target.shape)

# 配置网格搜索法使用的内核, C值
parameters = {'kernel':('linear', 'rbf'), 'C':[1, 10]}

# 创建分类器算法
svr = svm.SVC()

# 创建分类器
clf = grid_search.GridSearchCV(svr, parameters)

# 尝试parameters中的所有参数组合, 拟合数据
clf.fit(iris.data, iris.target)

# 输出结果
print(clf.score(iris.data, iris.target))
print(clf.best_params_)

执行, 输出

➜ test ✗ python3 gridSearchCV.py
/usr/local/lib/python3.6/site-packages/sklearn/cross_validation.py:41: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
  "This module will be removed in 0.20.", DeprecationWarning)
/usr/local/lib/python3.6/site-packages/sklearn/grid_search.py:42: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. This module will be removed in 0.20.
  DeprecationWarning)
(150, 4)
(150,)
0.9933333333333333
{'C': 1, 'kernel': 'linear'}

可以发现, 这里的R2 得分, 比我们之前直接使用cross_validation将数据分开来测试的结果要来的更加精确(详见Cross Validation in sklearn).

Cross Validation in sklearn

➜ test ✗ cat cross_validation.py
import numpy as np
from sklearn import cross_validation
from sklearn import datasets
from sklearn import svm

# 使用iris数据集
iris = datasets.load_iris()
print(iris.data.shape)
print(iris.target.shape)

# 将数据集分为两个部分: 60%为训练集, 40%为测试集
X_train, X_test, y_train, y_test = cross_validation.train_test_split(iris.data, iris.target, test_size = 0.4, random_state = 0)

# 输出分出来的训练/测试集大小
print(X_train.shape)
print(y_train.shape)
print(X_test.shape)
print(y_test.shape)

# 对使用SVC决策器数据进行拟合
clf = svm.SVC(kernel = 'linear', C = 1)
clf.fit(X_train, y_train)

# 输出测试集评分
print(clf.score(X_test, y_test))

执行输出结果

➜ test ✗ python3 cross_validation.py
/usr/local/lib/python3.6/site-packages/sklearn/cross_validation.py:41: DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
  "This module will be removed in 0.20.", DeprecationWarning)
(150, 4)
(150,)
(90, 4)
(90,)
(60, 4)
(60,)
0.9666666666666667

LinearRegression in sklearn

➜ test ✗ cat linearRegression.py
from sklearn import linear_model

# 训练数据集
X = [[0, 0], [1, 1], [2, 2]]
Y = [0, 1, 2]

# 创建线性回归对象
clf = linear_model.LinearRegression()

# 拟合数据
clf.fit(X, Y)

# 输出拟合出来的系数
print(clf.coef_)

# 输出拟合出来的截距
print(clf.intercept_)

# 预测结果
print(clf.predict([[3, 4]]))

# 输出训练集的R^2得分
print(clf.score(X, Y))
➜ test ✗ python3 linearRegression.py
/usr/local/lib/python3.6/site-packages/scipy/linalg/basic.py:1226: RuntimeWarning: internal gelsd driver lwork query error, required iwork dimension not returned. This is likely the result of LAPACK bug 0038, fixed in LAPACK 3.2.2 (released July 21, 2010). Falling back to 'gelss' driver.
  warnings.warn(mesg, RuntimeWarning)
[0.5 0.5]
1.1102230246251565e-16
[3.5]
1.0

Information Gain

关于信息增益计算

Informatio_Gain = Entropy(parent) - [weighted_average] * Entropy(children)

现有数据集

Grade Bumpiness Speed_Limit? Speed
steep bumpy yes slow
steep smooth yes slow
flat bumpy no fast
steep smooth no fast

计算Entropy(parent)的熵

在这个数据集中, parent为Speed, 我们需要计算Entropy(parent)的值.
关于熵的计算, 请查看此链接Entropy.

计算Grade的权重

Grade Bumpiness Speed_Limit? Speed
steep bumpy yes slow
steep smooth yes slow
flat bumpy no fast
steep smooth no fast
  • 如图所示, 我们在第一步已经用决策树将Speed分为slow和fast两个分支.
  • 将分成两个分支, 分支为值为steep的行; 第二分支为值为flat的行. 分别计算这两个部分的权重值.

计算分支的熵

  • 我们先计算左侧分支[ssf]的熵

手动统计概率:


用Python实现, 并存入List, 便于计算:

plist = [2 / 3, 1 / 3]

将其带入Entropy()得到答案:

➜ test ✗ python3 entropy.py
0.9182958340544896

后面计算时, 取小数点后四位, 四舍五入, 0.9183.

  • 接着计算右侧分支[s]的熵

手动统计概率:

plist = [1]

将其带入Entropy()得到答案:

➜ test ✗ python3 entropy.py
0.0

[weighted_average] * Entropy(children)计算



Information_Gain

Information_Gain = Entropy(parent) - [weighted_average] * Entropy(children)

Entropy

如何计算熵

  • 两种特殊情况
    最好的情况: 样本都是同类, 则Entropy值为0
    最差的情况: 样本均匀分布在所有类中, 则Entropy值为1
  • 现有数据集
Grade Bumpiness Speed_Limit? Speed
steep bumpy yes slow
steep smooth yes slow
flat bumpy no fast
steep smooth no fast

在这个数据集中, 什么因素可以决定当前应该加速还是减速.

  • Speed部分统计
    s->代表slow
    f->代表fast
    则数据集缩写为: [ssff]
    则slow的概率为:
    则fast的概率为:
  • 计算Speed节点的熵
➜ test ✗ cat entropy.py
import math

# 计算熵值
def entropy(input_list):
    result = 0
    for i in input_list:
        result -= i * math.log(i, 2)

    return(result)

# main run part
if __name__ == '__main__':
    # 这里为[P(slow), P(fast)]
    plist = [0.5, 0.5]

    # 输出计算结果
    print(entropy(plist))
  • 执行输出
➜ test ✗ python3 entropy.py
1.0

DecisionTree Classifier

➜ test ✗ cat DecisionTree.py
from sklearn import tree

# 训练集
X = [[0, 0], [1, 1]]
Y = [0, 1]

# 定义一个DecisionTreeClassifier分类器
clf = tree.DecisionTreeClassifier()

# 拟合X, Y数据
clf.fit(X, Y)

# 预测结果
print(clf.predict([[2, 2]]))

运行, 输出预测结果

➜ test ✗ python3 DecisionTree.py
[1]