机器学习之分类算法

写在前面

请先阅读机器学习之特征工程

sklearn转换器和估计器

转换器(transformer): 特征工程的父类

  1. 实例化(实例化的是一个转换器类(Transformer))
  2. 调用 fit_transform() 方法(对于文档建立分类词频矩阵,不能同时调用)

标准化:(x - mean) / std

fit_transform()
fit() 计算 每一行列的平均值、标准差
transform() (x - mean) / std 进行最终的转换


估计器(estimator): sklearn机器算法的实现

  1. 实例化一个estimator

  2. 调用fit()

    estimator.fit(x_train, y_train)  # 计算 生成模型
    # 调用完毕,模型生成
  3. 模型评估:

    i. 直接比对真实值和测试值

    y_predict = estimator.predict(x_test)
    y_test == y_predict # 生成一系列布尔值,Ture多则准确

    ii. 计算准确率

    accuracy = estimator.score(x_test, y_test)

介绍

分类算法用于将数据样本分配到不同的类别

算法

朴素贝叶斯

朴素贝叶斯算法:
朴素:假设特征与特征之间相互独立
应用场景:文本分类,单词作为特征
优点:分类效率稳定;对缺失数据不敏感,算法简单(贝叶斯公式),常用于文本分类;准确度高速度快
缺点:由于有“朴素”的假定,如果特征属性有关联时效果不好
贝叶斯公式: P(C | W) = P(W | C) * P(C) / P(W)

demo

from sklearn.naive_bayes import MultinomialNB
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from SelfTools import Tool
"""
MultinomialNB(alpha=1.0)
朴素贝叶斯分类
alpha: Laplace平滑系数
"""


def news_demo():
"""
朴素贝叶斯算法进行新闻分类
:return:
"""
# 获取数据
news = fetch_20newsgroups(subset="all")

# 划分数据集
x_train, x_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.2, random_state=6)

# 特征工程:文本特征值抽取
transfer = TfidfVectorizer()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)

# 朴素贝叶斯预估器流程
estimator = MultinomialNB()
estimator.fit(x_train, y_train)

# 模型评估
y_predict = estimator.predict(x_test)
print("y_predict:\n", y_predict)
print("y_predict == y_test:\n", y_predict == y_test)
Tool.separate()

print("score = ", estimator.score(x_test, y_test))
Tool.separate()
return None


if __name__ == "__main__":
news_demo()

knn

k-临近算法(k-Nearest Neighbour):近朱者赤,近墨者黑

如果一个样本在特征空间中的 k 个最相似(即特征空间中最邻近)的样本中的大多数都属于某个类别,则该样本也属于这个类别

=>第 1 近,第 2 近 ... 第 k 近

缺点:k 取得太小,容易受到异常点影响;k 取得太大,容易受到样本不均衡影响; 懒惰算法,内存开销大

注意:knn算法计算距离时需要对数据进行标准化处理,防止大数据的支配效果

适合小数据场景

demo

from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from SelfTools import Tool
"""
KNeighbourClassifier(n_neighbors=5, algorithm='auto')
n_neighbors: int, 可选(默认5),k_neighbors查询时默认使用的邻居数
algorithm: 选择算法,不必关注,使用'auto'自动选择最优即可
"""


# 鸢尾花种类预测
def iris_classify():
"""
knn算法对鸢尾花分类
数据集分为测试集和训练集
:return: class(Iris-Setosa, Iris-Versicolour, Iris-Virginica)
"""
# 获取数据
iris = load_iris()

# 数据集划分 训练集 + 测试集
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6) # 返回值固定形式

# 特征工程:数据标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train) # 对训练集标准化
x_test = transfer.transform(x_test)
# 测试集要用和训练集一样的处理方式,即均值与方差均与训练集一致,因为transfer在fit_transform()时计算过了均值方差,所以test直接使用transform()
# 如果test仍使用fit_transform()那相当于在用测试集的均值和方差
# 原因是transfer是一个固定的实例化对象,它在第一次调用fit_transform方法时均值和方差的属性就被修改完毕(被修改为训练集的均值和方差) 测试集沿用
# 再次执行又会被修改,测试集不希望发生修改

# knn预估器流程
estimator = KNeighborsClassifier(n_neighbors=3)
estimator.fit(x_train, y_train)

Tool.separate()
# 模型评估
# 法一:直接比对真实值和测试值
y_predict = estimator.predict(x_test)
print("y_predict:\n", y_predict)
print("y_predict == y_test: \n", y_test == y_predict)
Tool.separate()
# 法二:计算准确率
score = estimator.score(x_test, y_test)
print("score = ", score)
Tool.separate()

return None


if __name__ == "__main__":
iris_classify()

决策树

决策树
信息:用来消除随机不定性的东西
信息熵:衡量信息的依据
bit
信息熵 H(X) = - sum(P(xi) * log (b) P(xi)), i: [1, n]
决策树的划分依据之一:信息增益
特征A对训练数据集D的信息增益 g(D, A) 定义为集合D的信息熵H(D)与特征A给定条件下D的信息条件熵 H(D|A)之差
g(D, A) = H(D) - H(D|A)

决策树适用于大数据场景,是非懒惰算法,内存开销和效率优于knn,但准确率不如knn

demo

from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from SelfTools import Tool
from sklearn.datasets import load_iris
from sklearn.tree import export_graphviz

"""
DecisionTreeClassifier(criterion='gini', max_depth=None, random_rate=None)
决策树分类器
criterion: 默认'gini'系数,也可以选择信息增益的熵'entropy'
max_depth: 树的深度大小
random_rate: 随机数种子

决策树可视化
export_graphviz(estimator, out_file='tree.dot', feature_names=["."])
导出DOT格式
"""


def decision_tree():
"""
决策树对鸢尾花分类
:return:
"""
# 获取数据集
iris = load_iris()

# 划分数据集
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)

# (决策树不需要就算距离,因此不需要标准化)
transfer = None
# 决策树预估器进行分类
estimator = DecisionTreeClassifier(criterion='entropy')
estimator.fit(x_train, y_train)

# 模型评估
y_predict = estimator.predict(x_test)
print("y_predict:\n", y_predict)
print("y_predict == y_test:\n", y_predict == y_test)
Tool.separate()

print("score = ", estimator.score(x_test, y_test))
Tool.separate()

export_graphviz(estimator, out_file='decision_tree.dot', feature_names=iris.feature_names)
# 可视化决策树http://www.webgraphviz.com/,将dot文件传入
return None


if __name__ == "__main__":
decision_tree()

随机森林

包含多个决策树的分类器

原理:一棵决策树可能有误差;建立一堆决策树,独立预测,结果取众数,少数服从多数

例如:训练了5个树,4个树True,1个树False,结果就是True
随机森林原理过程:
训练集:特征值、目标值
随机:训练集随机,特征随机(如果每次都用一样的数据,训练结果岂不是一样?)
假设训练集有 N 个样本,M 个特征
训练集随机:bootstrap 随机有放回抽样,N 个样本的训练集随机有放回抽样 N 次(一次一个),得到一个新的随机训练集
如: [1, 2, 3, 4, 5] -> [2, 2, 3, 1, 5]
特征随机:M 个特征中抽取 m 个特征,要求: M >> m

demo

TBD~

from sklearn.ensemble import RandomForestClassifier
"""
RandomForestClassifier(n_estimators=10, criterion='gini', max_depth=None, max_features='auto',bootstrap=True,
random_state=None, min_samples_split=2, min_samples_leaf)
随机森林分类器
n_estimators: optional, number of trees in forests, integer
criterion: optional, measures of splitting features, string
max_depth: optional, max depth of one tree, integer or None
max_features: max features of one tree
if 'auto', max_features = sqrt(n_features)
if 'sqrt', same as 'auto'
if 'log2', max_features = log2 (n_features)
if None, max_features = n_features (Not recommended)
string
bootstrap: optional, whether using bootstrap, boolean
min_samples_split: min number of samples of samples' split
min_samples_leaf: min number of samples of leaf node
超参数:n_estimators, max_depth, min_samples_split, min_samples_leaf
-> 网格搜索用
"""


def rf_demo():
"""
随机森林
:return:
"""
# TODO
return None


if __name__ == "__main__":
rf_demo()

实例

TBD~

# http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt
import pandas as pd


def titanic_predict():
"""
Titanic号乘客生存预测
:return:
"""
# 获取数据
path = "http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt"
titanic = pd.read_csv(path)
# 数据处理:titanic.txt缺失age属性:缺失值处理;特征值->字典类型

# 准备好特征值、目标值

# 划分数据集

# 特征工程:字典特征抽取

# 决策树预估器流程

# 模型评估
return None


if __name__ == "__main__":
titanic_predict()

(•‿•)