Data Analysis
算法基础, 工具框架算法模型的选择使用, 业务方面(金融等)
需要掌握 算法推导过程
了解大数据系统 (架构层, 算法是核心层)
数据获取途径: 爬虫, 大数据架构, 购买
数据挖掘(numpy, pandas, matplotlib ... ...)----
图像识别(在物联网中的应用, 无人驾驶技术, 自动泊车) nlp
numpy
核心数据结构是数组(二维以上就是矩阵, 一维数组是行向量)
- 创建
(1) list创建
copy列表, 把列表中的元素类型统一化(object > float > int > boolean)然后根据统一化以后列表创建数组对象(数组中的元素类型都一致)
列表在双肩数组的时候需要每个维度上的元素个数保持一致
(2) 内建函数
ones()
zeros()
full()
eye() 对角线上为1 其他为0
linspace(start, stop, num=50)
logspace(start, stop, num=50) 指数 1 - 10
arange(start, stop, step) 去下标
random.randint(low, hight, size)
random.randn() 标准正态分布
random.narmal() 正态分布
random.random() 0 - 1 随机浮点数 - 属性
ndim 维度
size 大小
shape 形状
dtype 数据类型
itemsize 每个元素的字节数 (float双精度的浮点64位 8个字节, 布尔类型一个字节)
data 内存地址 - ndarray的基本操作
- 索引
所有的列表索引方式, 数组都使用a = np.array([[1, 2, 3], [4, 5, 6]])
列表索引方式a[0][0]
数组特有的索引方式a[0, 1]
或a[[1, 0, 1]]
- 切片
a[起始 : 终止 : 步长]
步长为正: 从前向后切,
步长为负: 从后向前切, - 变形
- 变形前后size值保持一致
-
reshape(size=())
把原来的数组copy出一个副本对副本进行变形并返回 -
resize(size=())
直接在原数组上进行变形
- 级联
- 维度一致才能级联
- 形状相符才能级联(将axis的取值所在维度盖住看其他维度是否形状一致)
- axis 指定级联的方向
针对于矩阵还有hstack()
和vsrack()
h
是把二维数组变成一维(行向量)
v
是把一维数组变成 n 行 1 列的二维数组(列向量)
- 切分
split(数组, [切分点, ... ...], axis=0 )
vsplit
纵向上切 切的是0维度
hspilt
横向上切 切的是1维度
- 索引
- 矩阵运算
- 矩阵与矩阵
+
-
(两个矩阵之间形状size要一致) - 矩阵与矩阵乘
np.dot()
矩阵乘分为点乘(内积)和叉乘(外积) - 矩阵与常数
*
/
- 广播机制原则
- 当向量或者常数与矩阵进行运算的时候, 可以把向量或者常数补全成矩阵的形状
- 我们可以把一个常数按照任何一个矩阵的形状进行扩充
- 向量和矩阵相加减(要求: 如果是行向量那么元素的个数要和矩阵的列数一致, 因为按行扩充)(如果是列向量, 那么行数要和矩阵的行数一致, 按列扩充), 根据行数或者列数把向量进行扩充
- 矩阵与矩阵
- 数组的聚合
- 完全聚合: 不指定 axis 的值, 则把所有的数据聚合在一起
- 聚合时将
np.nan
剔除 - 指定轴聚合: 用 axis 来指定对哪些维度进行聚合
- axis 值等于哪个维度, 这个维度就会消失, 取而代之的是把这个维度上的子元素进行某种聚合的结果
pandas
Series、 DataFrame、 Pannel
- Series
构成: index 和 values
# 字典是 哈希结构(散列结构), 数组是线性结构
# 字典的查找(哈希算法找)效率比数组的查找(先找到首元素再根据下标)效率快,</pre>
series在查找的时候既可以用下标(隐式索引)来查找又可以用 index(显式索引)来查找
- 创建
- 用数组或者列表来创建
创建的时候要指定 values 部分对应的内容和 index 部分对应的内容, values就是数组或列表种具体的值, index 的值如果不指定, 默认会把数组的下标设置为 index, 如果指定, 制定的时候 index 的个数和 values 的个数保持一致
s = pd.series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])
- 用字典来创建
系统会把字典的所有的值 copy 出放在 values 部分, 所有键 copy 出放在对应的index部分, 字典的除了自带的index 以外, 也可以指定 index, 这个指定的 index 可以和原字典的 index 不保持一致, 不一致的地方会设置为 nan
s = pd.series(data={'a': 1, 'b': 2, 'c': 3, 'd': 4})
- 用数组或者列表来创建
- 索引与切片
- 显示索引(即用 index 作为索引)
s['a']
===s.loc['a']
- 隐式索引(用values的下标作为索引)
s.iloc[0]
- 隐式切片(实质上切实calues数组)
s.iloc[0: 2]
- 显示切片(对 index 进行切)
s.loc['a': 'c']
注意: c如果重复切不连续, 则不能以c为切片的断点
- 显示索引(即用 index 作为索引)
- 基本操作
- 属性:shape, size, index, values, name
- 确实检测: isnull(), notnull()
- 扩展: 有 seriesA 和 seriesB , A 和 B 的 index 完全一致但是 B 的 values全是boolean, 那么 B 可以作为 A 的索引使用, 此时输出的内容是B 中为True的那些索引对应的内容
- Series 的运算
- 适合 numpy 的运算都适合 Series
- Series 之间的运算
索引对应的那些元素的值进行数学运算, 运算的结果还对应相关索引
如果索引 index 不对应情况, 将缺失的 index 补充 NAN 在进行运算
- DataFrame 数据表
结构: index、 column、 values 分别代表行索引, 列索引, 值
一个DataFrame 由多个Series构成, 按行的话, 每一行都是一个Series, 如果按列, 每一列都是一个Series- 创建
- 数组: 指定index, colunms 和 values
- 字典: 每个键值对应的是一列, 键代表这一列的列索引, 值代表这个列名下对应的那些值
df = DataFrame({'a': [1, 2, 3, 4], 'b':[3, 4, 5, 6], 'c':[1, 5, 7, 8]})
- 索引与切片
- 索引列
列不能直接用列名进行切片 df['a': 'c']
df['a']
或df.a
- 索引行
显式df.loc['a']
df.loc['a': 'c']
df.loc[['a', 'b', 'c']]
隐式df.iloc[0]
df.iloc[0: 2]
df.iloc[[0, 1, 1]]
- 索引列
- 索引具体元素
df['a'][0]
df['a', 0] 这是错误的 不允许先列后行
df.loc[0, 'a']
df.loc[::, 'a':'c']
df.iloc[::, 0: 2]
- 创建
- DataFrame 的运算
- DataFrame之间的运算
遵从自动补全机制 - DataFrame 和 Series 之间的运算
如果Series 的 index 是行索引 在运算的时候要指定 axis 为 0,
如果 Series的 index 是列索引 在运算的时候要指定 axis 为 1,
- DataFrame之间的运算
- 数据的过滤与清晰
- 缺失值的处理
标准的python缺失值np.nan
检测具体某个位置的缺失isnull()
和notnull()
与any()
和all()
配合使用- 过滤
dropna(axis=0)
- 填充
fillna()
用具体值填充, 向前填充, 向后填充
- 过滤
- 异常值的处理
在实际业务中规定某些范围的值就是异常值, 处理异常值也要根据实际业务(删除、 修正) - 重复值(行)
不是第一次出现的都是重复
- 缺失值的处理
- 层次化索引
- 层次化索引创建
- 层次化索引的查找与切片
只有暴露在最外层的索引才能直接查找与切片 - 索引堆
stack()
和unstack()
stack(level = -1)
level 等于哪一层次, 她就会消失出现在列中
unstack(level = -1)
level 等于哪一层次, 她就会消失出现在列中
- 拼接
- 级联
pd.concat([df1, df2], axis=0)
- 简单级联
对行级联, 列名一致 - 不匹配级联
对行级联, 列名不一致
内连接join='outer'
(不匹配的补nan), 外连接join='inner'
(不匹配的去掉), 指定轴链接join_axes=[df1.columns]
(只保留指定的轴)join_axes=[pd.Index(['A', 'C'])
- 简单级联
- 合并
和并要求两个二维表有一个或者多个公共属性, 用公共属性作为合并的key值进行拼接;如果两个表没有公共属性那么不能直接合并- 一对一
df1.merge(df2)
- 一对多 把一个复制成多份 再合并
- 多对多 组合
如果出现不匹配的情况则 - 内合并:
how='inner'
不匹配的部分剃掉 - 外合并: 不匹配的地方补nan
- 左合并: 按左边为基准合并
- 右合并:
多个公共属性时 - 指定以某一属性为key
df1.merge(df2, on=['name'], suffixes=['age1', 'age2'])
没有公共属性时 df1.merge(df2, left_on=['name'], right_on=['名字'])
- 一对一
- 级联
- 映射
在一个关系表中把某些值和特定的键绑定在一起构成映射
如:
{'a': 1, 'b': 2}
y = 2 * x + 1, y = x ** 2 + 1
def func(x):
return x ** 2 # 函数 功能模块的封装(面向对象:继承,封装,多态)
lambda x: x * 2 + 1
df1['job'][df1.job == 'driver'] = 'cooker'
替换元素 df.replace({'原来的元素': '替换的元素'})
根据已知列映射出新列 df['新的列名'] = df['已存在的列名'].map({'已存在列的元素': '映射结果'})
def func(x):
if x > 60 :
return '及格'
else:
return '不及格'
# df['是否及格'] = df['成绩'].map(func)
- 分组聚合
df.groupby['color'][['price']].sum()
按颜色求价格的和 - 绘图
折线图、 柱状图、 直方图、概率密度曲线
scipy
高端科学计算工具包
- 傅里叶变换
fft()
过滤高频信号 - 微积分
integrate.qual(积分方程, 积分上限, 积分下限)
方程: y = x ** 2 在(x0, xn)的面积
x0^2dx + x1^2dx + ... ... + xn^2dx
= f(0~2)x^2dx = (1/3)x^3|0~2 = 8/3 </pre>
- 图像处理
移动shift()
旋转rotate()
缩放zoom()
高斯滤波from scipy import ndimage
ndimage.gaussian_filter()
中位数滤波ndimage.median_filter()
signal维纳滤波from scipy import signal
signal.wiener(moon, size=5)
matplotlib
- 图形基础
matplotlib 中基本的绘图元素包括 坐标轴、 坐标轴刻度、 绘图区域、- 2D曲线
单个 plot() 参数传一个数组或者两个数组
多条: 用多个 plot() 函数绘制 用 plot.show() 统一显示 也可以plt.plot(x1, y1, x2, y2, x3, y3)
彩图转灰度图 可以使用 聚合, rgb加权 - 2D曲线的属性设置
网格线plt
, 轴面与子轴面, 坐标轴的样式与界限, 坐标轴的标签plt.ysticks([-1, 0, 1])
、 图例legend()
线性linestyle
样式marker
颜色color
背景色 透明度 - 2D图形
直方图plt.hist
、 条形图plt.bar
、 饼图plt.pie
、 散点图plt.scatter
、 玫瑰图(极坐标) - 3D图形
- 2D曲线
Machine learning
- 经验
经验即是数据, 客观世界中一切事物都可以用数据来表示, 一般情况我们表示客观食物的时候, 习惯用他们的一些特征量化描述, 一般这些特征可以组合成一个向量, 即特征向量
数据是机器学习的基础 - 任务
根据数据模型和算法模型的不同可以将机器学习氛围监督学习和无监督学习- 监督学习
主要任务(理念): 利用现有数据推测未知数据
数据特点: 数据有两部分, 即特征数据和标签数据- 分类: 标签数据是离散的, 相互无关联的, 明确的(水果种类)
- 回归: 标签数据是连续的, 相互关联的, 不明确的(房价)
算法: K-近邻、线性回归器、 逻辑斯蒂回归、 朴素贝叶斯、 决策树、 随机森林、 SVM ... ...
- 无监督学习
对客观事物本身的特征进行分析与认知
数据特点: 只有特征数据- 聚类: K-Means(根据指标,簇之间的离散程度和聚合程度达到最优)
- 特征降维: PCA 主成分分析法
- 监督学习
- 性能
- 完成既定任务的质量的评测指标:
分类问题: 准确率, 精准率, 召回率, F1指标
回归问题: 均方误差, 平均绝对误差 - 性能调优
从数据上: 数据的正则化, 数据的标准化 ... ...
从算法上: 不同的算法通过调参进行性能调优
- 完成既定任务的质量的评测指标:
深度学习
神经网络: 基础神经网络, 俊基神经网络, 循环神经网络, 框架TensorFlow
监督学习算法
K nearest nerghbour
from sklearn.neighbours import KNerghborsClassifier, KNeighborsRegressor
- 欧氏距离 Euclidean Distance (欧几里得距离)
- K-近邻算法的原理
- 求某个样本点到所有已知样本点之间的距离, 得到 d1, d2, ... ... dn
- 对以上的距离进行从小到大的排序
- 对以上排序完的那些距离取前K个( <=20 )
- 对这前K个距离对应的标签进行分析, 如果某个标签占优势, 那么未知点就归属于这个标签
- 优缺点
优点: 精度高, 算法简单, 无需输入假定数据
缺点: 时间复杂度 和 空间复杂度 高 - 回归模型的原理是计算K近邻欧氏距离的平均值进行拟合回归
LinearRegression *
from sklearn.linear_model import LinearRegression
lr = LinearRegression(fit_intercopt=True, noemalize=False, copy_X=True, n_jobs=None)
# fit_intercopt 是否计算截距
# noemalize在计算拮据的情况下, 回归前归一化, 回归因子X为减去均值,除以L2范数
# copy_X复制或覆盖
# n_jobs 采用多少CPU计算 n_jobs=-1 有多少用多少</pre>
- 线性方程
y = w1x1 + w2x2 + ... ... + wnxn + b
令 W = (w1, w2 ... ... wn), X = (x1, x2, ... ... xn)
则 y = W * X ^ T + b
称 W 为回归系数, X 为特征向量, b 为截距 - 线性方程的推导
现有 m 个已知样本, 每个样本有 n 个特征记为 X1, X2, ... ... , Xm 每个X中都有 n 个 x
对应的标签记为: y1, y2, ... ... , ym ,且特征和标签成线性关系
此时只要求得 W 就可得到线性回归方程
将m个已知量带入方程会得到方程组:
y1 = W * X1 ^ T + b = w1x1_1 + w2x1_2 + ... ... + wnx1_n + b
y2 = W * X2 ^ T + b = w1x2_1 + w2x2_2 + ... ... + wnx2_n + b
... ...
ym = W * Xm ^ T + b = w1xm_1 + w2xm_2 + ... ... + wnxm_n + b
讨论: m > n 且无共线, 方程无解
m = n 且无共线, 有且只有一个解
m < n 无数个解
在实际生产环境中 m >> n (样本数远远大于特征维度), 所以上述方案行不通 - 最小二乘法
- 假设 W’ 和 b‘ 是最合适的, 得到假设出来的回归方程: W‘ * X ^ T + b’
- 把所有的样本带入, 得到假设的那些标签数据:
y1' = W' * X1 ^ T + b'
y2' = W' * X2 ^ T + b'
... ...
ym' = W' * Xm ^ T + b'
此时 y1', y2', ... .. , ym' 都是通过假设的 W' 和 b‘ 得到的标签, 那么真实的标签 y1, y2, ... .. , ym 和假设推导的标签之间一定存在差异 - 求真实的标签和假设推导的标签之间存在的差异 (因为差异有正负 所以采用平方)
H = (y1' - y1) ^ 2 + (y2' -y2) ^ 2 + ... ... + (ym' -ym) ^ 2
将推导量带入得到
H = (W'X1 ^ T - y1) ^ 2 + (W'X2 ^ T - y2) ^ 2 + ... ... + (W'Xm ^ T - ym) ^ 2 - 求差异的最小值
对 H 求导 为 0 得到极小值点
H’ = 2[W' * X1 ^ T - X1 ^ T * y1] + ... + 2[W' * Xm ^ T - Xm ^ T * ym]
令 X = (X1, X2, ... ... , Xm) Y = (y1, y2, ... ... , ym)
H' = 2W'X^T - 2X^TY
令 H‘ = 0 得到极小值
W'X^T * X = X^TY * X
X^T * X 是否可逆?- 如果可逆 W’ = (X ^ T * X)^(-1) * X ^ T * y * X
行列式不等于0 满秩矩阵 - 不可逆 引入岭回归 W'*(X^T * X + λI) = X^TY * X 【I是单位矩阵(对角线为1), λ为缩减系数】
此时 W‘ 的值除了受已知数据的影响以外还受 λ 的影响
W' = (X^T * X + λI)^(-1) * X^TY * X
from sklearn.linear_model import Ridge
改良的最小二乘法
1.岭回归可以解决特征数量比样本量多的问题
2.岭回归作为一种缩减算法可以判断哪些特征重要或者不重要,有点类似于降维的效果
3.缩减算法可以看作是对一个模型增加偏差的同时减少方差
岭回归用于处理下面两类问题:
1.数据点少于变量个数
2.变量间存在共线性(最小二乘回归得到的系数不稳定,方差很大) -
from sklearn.learn_model import Lasso
罗斯回归与岭回归的区别是罗斯回归采用L1正则:惩罚系数的绝对值
- 如果可逆 W’ = (X ^ T * X)^(-1) * X ^ T * y * X
逻辑斯蒂
from sklearn.learn_model import LogisiticRegression
计算量非常小,速度很快,存储资源低,缺点就是因为模型简单,对于复杂的情况下会出现欠拟合,并且只能处理2分类问题, 信用评测, 营销活动成功率概率, 产品销售预测,
特征向量: X = (x1, x2, ... ... , xn)
回归系数: W = (w1, w2, ... ... , wn)
截距: b
标签: Y
如果 Y 和 X 成线性关系, 且 Y 是连续的, 则可以表示成: Y = W * X ^ T + b
-
二分类问题: 在实数 R 的范围内把 Y 进行二分类, 即把 Y 映射到集合{0, 1}中, 把 Y 映射到(0, 1) 区间中, 然后进行二分类。(例如糖尿病案例中的标签是医学指标需要使用单位阶跃函数转为二分类问题)
现在需要找到一个函数具有性质: 单调递增, 作用于(-∞, +∞), 值域(0, 1)
逻辑斯蒂函数 g(z) = 1/(1 + e^(-z))
g(z)' = [1/(1 + e(-z))2] * (e^(-z)) > 0 单调递增
作用域: R, 值域: z趋向于 -∞ g(z) 趋向于 0 ; z趋向于 +∞ g(z) 趋向于 1
选择分类点: z< 0 g(z)<0.5 认为是0
z>0 g(Z)>0.5 认为是1
g(y) = 1/(1 + e^(-y)) -------- g(x) = 1/(1 + e ^ ( - W * x ^ T - b))
此时 g(x) 是 推导的标签 是离散的 因此不能用最小二乘法
-
最大似然估计
X1 对应 Y1 这件事发生的概率, 记为 P(X=X1, Y=Y1)
... ...
Xm 对应 Ym 这件事发生的概率, 记为 P(X=Xm, Y=Ym)
目标: 求上述事件(相互独立)同时发生的是最大概率 : P = P(X=X1, Y=Y1)P(X=X2, Y=Y2)...(X=Xm, Y=Ym)
-
构造似然函数(损失函数)
P(x, y) = (g(x) ^ y) * (1 - g(x)) ^ (1 - y))
带入样本
P(X1, Y1) = (g(X1) ^ Y1) * (1 - g(X1)) ^ (1 - Y1))
... ...
P(Xm, Ym) = (g(Xm) ^ Ym) * (1 - g(Xm)) ^ (1 - Ym))
总概率:
L(W, b) = P(X1, Y1)...P(Xm, Ym) = [(g(X1) ^ Y1) * (1-g(X1)) ^ (1-Y1))]...[(g(Xm) ^ Ym) * (1-g(Xm)) ^ (1-Ym))]
-
求似然函数的最大值
连乘求导过于麻烦, 引入 ln 将连乘变成连加
lnL(W, b) = ln[[(g(X1) ^ Y1) * (1-g(X1)) ^ (1-Y1))]...[(g(Xm) ^ Ym) * (1-g(Xm)) ^ (1-Ym))]]
= ln[[(g(X1) ^ Y1) * (1-g(X1)) ^ (1-Y1))]] + ... + ln[[(g(Xm) ^ Ym) * (1-g(Xm)) ^ (1-Ym))]]
求导 L(W, b)' = 0的到最合适的 W (仅限于W有一个值, 如果有多个值则引入梯度下降或拟牛顿法求解)
-
-
梯度下降 (常用于优化算法,线性收敛的随机优化算法)
from sklearn.learn_model import SGDClassifier
梯度的方向是最大方向导数的方向
-
二维空间中
y = x ^ 2
微分 dy = dx ^ 2 = 2x dx
在点(1, 1) 处dy = 2 即为切线的斜率 , 下降最快的方向
-
三维空间中
z = x ^ 2 + y ^ 2
过三维曲面中的某个点可以做无数条切线, 其中梯度方向的切线是下降最快的
-
求偏导数
δz/δx 对 x 的偏导数 2x ; δz/δy 对 y 的偏导数 2x
-
梯度方向向量
(δz/δx, δz/δy) = (2x, 2y)
梯度下降的过程:
-
二维空间 J(x) = x ^ 2
求梯度: 二维空间的梯度就是微分 J(x)' = 2x
初始化一个起始点 x0
设置学习步长(学习率) α = 0.4
-
根据梯度下降公式, 不断的迭代, 直至下降到合适的位置
案例 J(x) = x ^ 2, x0 = 1, J(x)' = 2x, α = 0.4
x1 = x0 - 0.4 * 2 * 1 = 0.2
x2 = x1 - 0.4 * 2 * 0.2 = 0.04
... ...
-
三维空间 Z = X ^ 2 + Y ^ 2
求梯度 (2x, 2y)
设置起始点 p0(3, 4)
设置学习率 α = 0.1
-
迭代下降
p1 = p0 - 0.1 * (2 * 3, 2 * 4) = (2.4, 3.2)
... ...
-
朴素贝叶斯
from sklearn.naive_bayes import GaussianNB, MultionmialNB, BernoulliNB
高斯, 多项式文本分类, 伯努利文本分类多适用于小型文本,
-
条件概率
P(A|B) = P(AB) / P(B) <===> P(AB) = P(A|B)P(B)
在 B 已经发生的基础上 A 发生的概率, A 和 B 是相互独立事件
-
全概率
全概率公式表达的是由因溯果
-
贝叶斯公式
由果溯因, 事件已经发生, 推测是哪个因素造成的
-
朴素贝叶斯分类器基于贝叶斯理论及其假设(即特征之间是独立的,互不相互影响的)
P(A|B) = P(B|A)P(A) / P(B)
P(A|B) 是后验概率, P(B|A)是似然 P(A)是先验概率 ,P(B)是预测的值
具体应用: 垃圾邮件检测, 文章分类, 情感分类, 人脸识别
SVM *
from sklearn.svm import SVC, SVR
在N维空间找到一个(N-1)维的超平面将样本空间分为两类。
具体应用: 广告展示, 性别检测, 大规模图像识别
通过核函数,支持向量机可以将特征向量映射到更高维的空间中,是的原本线性不可分的数据在映射之后的空间中变得线性可分。
在是显示不需要直接对特征向量做映射,耳式用核函数对两个特征响亮的内积进行变换,这样做等价于先对箱量进行映射然后做内积。
[图片上传失败...(image-3f220a-1551434906070)]
决策树 *
from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
线性结构(列表 栈 队列)、 散列结构 、 树形结构 (至多有一个前驱, 可以有多个后继) 、 网络结构(有方向的图)
- 参数说明
class sklearn.tree.DecisionTreeClassifier(criterion='gini', splitter='best', max_depth=None, min_samples_split=2,min_samples_leaf =1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None,class_weight=None, presort=False)
'''
criterion:string类型,可选(默认为"gini")
衡量分类的质量。支持的标准有"gini"代表的是Gini impurity(不纯度)与"entropy"代表的是information gain(信息增益)。
splitter:string类型,可选(默认为"best")
一种用来在节点中选择分类的策略。支持的策略有"best",选择最好的分类,"random"选择最好的随机分类。
max_features:int,float,string or None 可选(默认为None)
在进行分类时需要考虑的特征数。
1.如果是int,在每次分类是都要考虑max_features个特征。
2.如果是float,那么max_features是一个百分率并且分类时需要考虑的特征数是int(max_features*n_features,其中n_features是训练完成时发特征数)。
3.如果是auto,max_features=sqrt(n_features)
4.如果是sqrt,max_features=sqrt(n_features)
5.如果是log2,max_features=log2(n_features)
6.如果是None,max_features=n_features
注意:至少找到一个样本点有效的被分类时,搜索分类才会停止。
max_depth:int or None,可选(默认为"None")
表示树的最大深度。如果是"None",则节点会一直扩展直到所有的叶子都是纯的或者所有的叶子节点都包含少于min_samples_split个样本点。忽视max_leaf_nodes是不是为None。
min_samples_split:int,float,可选(默认为2)
区分一个内部节点需要的最少的样本数。
1.如果是int,将其最为最小的样本数。
2.如果是float,min_samples_split是一个百分率并且ceil(min_samples_split*n_samples)是每个分类需要的样本数。ceil是取大于或等于指定表达式的最小整数。
min_samples_leaf:int,float,可选(默认为1)
一个叶节点所需要的最小样本数:
1.如果是int,则其为最小样本数
2.如果是float,则它是一个百分率并且ceil(min_samples_leaf*n_samples)是每个节点所需的样本数。
min_weight_fraction_leaf:float,可选(默认为0)
一个叶节点的输入样本所需要的最小的加权分数。
max_leaf_nodes:int,None 可选(默认为None)
在最优方法中使用max_leaf_nodes构建一个树。最好的节点是在杂质相对减少。如果是None则对叶节点的数目没有限制。如果不是None则不考虑max_depth.
class_weight:dict,list of dicts,"Banlanced" or None,可选(默认为None)
表示在表{class_label:weight}中的类的关联权值。如果没有指定,所有类的权值都为1。对于多输出问题,一列字典的顺序可以与一列y的次序相同。
"balanced"模型使用y的值去自动适应权值,并且是以输入数据中类的频率的反比例。如:n_samples/(n_classes*np.bincount(y))。
对于多输出,每列y的权值都会想乘。
如果sample_weight已经指定了,这些权值将于samples以合适的方法相乘。
random_state:int,RandomState instance or None
如果是int,random_state 是随机数字发生器的种子;如果是RandomState,random_state是随机数字发生器,如果是None,随机数字发生器是np.random使用的RandomState instance.
persort:bool,可选(默认为False)
是否预分类数据以加速训练时最好分类的查找。在有大数据集的决策树中,如果设为true可能会减慢训练的过程。当使用一个小数据集或者一个深度受限的决策树中,可以减速训练的过程。
'''
decision_tree.feature_importances_ # 查看属性的重要性
绘制一棵决策树 pip install graphviz (并配置环境变量)
import graphviz
dot = sklearn.tree.export_graphviz(decison_tree, out_file=None, max_depth=None, filled=None)
graphviz.Source(dot) # filled 填充颜色</pre>
决策树算法
-
决策树的定义:
用非叶子表示模型的特征用叶子节点来表示标签
每一个分支都是当前特征在特定值域上的输出
-
如何构造以可决策树
关键: 属性的分裂, 如何在某个节点处根据属性的不同构造不同的输出
理论基础: 信息论
三种情况
- 属性是离散的并且不要求构建二叉树(有多少中取值就够贱多少个分支)
- 属性是离散的需要构建二叉树(将离散的标签按照需求归类)
- 属性是连续的(取若干个区间 将对应的值划分到区间中进行分类)
ID3 算法
- 信息量 :
如果参与分类的事物可以划分到多个分类中去, 记 X 为该信息, 则该信息的信息量为:(比如X可以划分为n个类别, 则第i个类别的信息量为 L(xi) = -log2(P(xi)), P(xi)表示xi出现的概率)
数学期望(mean)(或均值,亦简称期望)是试验中每次可能结果的概率乘以其结果的总和,是最基本的数学特征之一。它反映随机变量平均取值的大小 - 信息熵(香浓熵):
H = L(X1)P(X1) + ... ... + L(Xn)P(Xn)
例如: 11个人中5个贷款6个不贷款 H = -5/11 * log2(5/11) -6/11 * log2(6/11) = 0.994 - 计算每一个特征 相对 类别的划分 的熵:
例如: 11个人中 3个自由职业者中有一个贷款, 4个工人1个贷款 4个白领3个贷款
则: info = 3/11 * (-1/3 * log2(1/3) - 2/3 * log2(2/3))+ 4/11 * 1/4(-1/4 * log2(1/4) - 3/4 * log2(3/4)) + 4/11 * (-3/4 * log2(3/4) - 1/4 * log2(1/4)) = 0.840 - 计算每一个特征的信息增益:
信息熵 - 每个特征相对类别划分的熵 = 0.994 - 0.840 = 0.154
对计算的结果进行比较。
C4.5决策树:
为了解决ID3决策树的缺点:当一个属性值可取数目较多时, 那么可能这个属性对应的可取值下的样本只有一个或者很少个, 此时信息增益非常高, ID3算法会认为这个属性非常适合用来划分, 但较多属性来进行划分带来的问题是他的泛化能力很弱, 不能对新样本进行有效的预测。
所以C4.5 采用信息增益率来作为划分依据:
但是增增益率会偏好取值数目较少的属性, 因此C4.5决策树会先从候选划分属性中找出信息增益高于平均水平的属性,再从中选择增益率最高的
CART 算法:
-
也叫分类回归树, 既能分类有能回归
CART是一颗二叉树
如果是CART分类树, 采用GINI值来作为节点分裂的依据;如果是CART回归树, 采用样本的最小方差作为节点的分裂依据
如何选择分裂属性
-
GINI 值的计算
GINI = 1 - [P1 ^ 2 + P2 ^ 2 + ... ... + Pn ^ 2] 节点的纯度越低, GINI 值越大 (越小属性越重要)
-
回归方程的方差: δ = [(x1 - u) ^ 2 + (x2 - u) ^ 2 + ... ... + (xn - u) ^ 2] ^ 0.5
方差越大, 数据越离散, 预测的性能就越低
-
如何分裂成一颗二叉树
集成算法
ada,gbdt, xgboost 常用 max_depth = 6, 而 decision_tree , randomForest 常用 max_depth = 15
boosting 提升
学习器之间存在先后顺序,初始时。每个样本的权重相等,首先第一个学习器训练样本进行学习,学习完成后,增大错误样本的权重,同时减小正确样本的权重,再利用第二个学习期对其进行学习,依次进行下去,最终得到b个学习器。最终合并b个学习其的结果,同时与bagging的不同的是,每个学习器的权重也不一样。
Adaboost
from sklearn.ensemble import AdaBoostClassidier
重复选择表现一般的模型,每次基于先前模型的表现进行调整, 不同的是 ada是通过提升数据点的权重来定位模型的不足,而gbdt是通过算梯度定位模型的不足,因此 gbdt可使用更多种类的不妙函数,而这主要区别在于 识别模型的问题,ada用错分数据来识别问题,通过调整错分数据的权重来进行模型的改进。 gbdt梯度提升树通过计算梯度来改进。
GBDT
CART 作为基分类器。
每棵树学的是之前树的残差(预测值为前面所有树累加的和)
后面的学习器纠正前面的所有若学习器的残差,最终将多个学习器像加在一起用来进行最终的预测(每一次计算都是为了减少上一次的残差,即利用残差学模型, 为了消除残差,会在残差减少的梯度方向上减少一个新的模型)
梯度提升树 进行特征重要性排序
from sklearn.ensemble import GradientBosstingClassifier
gbdt = GradientBosstingClassifier(n_estimators,learning_rate=0.2, )
gbdt.fit(data, target)
fi = gbdt.feature_importances_.argsort()[::-1] # 特征重要性的索引排序
</pre>
XGBOOST
pip install xgboost
GBDT 的极端化,2014年 陈天奇
from xgboost.sklearn import XGBClassifier
支持线性分类器,相当于带L1 和L2 正则化项的LR或线性回归。
xgboost,plot_importance(xgb)
显示属性重要性排序
xgboost.plot_tree(xgb, num_tree=0,ax=axes)
绘制索引为0的树
构造损失函数: 真实值与预测值的 均方误差/ 似然函数
求损失函数的最小值
用集成学习算法表示预测值 yi' = f1(xi) + f2(xi) + ... ... + fk(xi), f代表每一棵树映射函数
找到最合适的 K
-
原理 https://www.jianshu.com/p/7467e616f227
data = xgb.DMatrix ('data.txt')
加载数据存在DMatrix对象中,每一行代表一个样本 有 属性索引 和 属性值
-
优势
正则化
并行处理
高度灵活:用户自定义优化目标和评价标准
缺失值处理:内置处理缺失值的规则,XGBoost在不同节点遇到缺失值时采用不同的处理方法。并且会学习未来遇到缺失值时的处理方法。
剪枝:党分裂遇到付损失时GBDT会提u能告知分裂,因此GBDT时贪心算法, XGBoost会一直分裂到指定的最大深度,然后回过头剪枝。
内置交叉验证:在每一轮迭代中使用交叉验证,可以方便获得最优迭代次数,而GBDT是用网格搜索智能检测有限个值。
在已有的模型基础上继续学习
-
参数调优https://www.cnblogs.com/mfryf/p/6293814.html
booster 选择每次迭代的模型
gbtree
基于树的模型(默认)
gbliner
线性模型silent 但这个参数值为1时 静默模式开启 不会输出任何信息,一般保持默认0,帮助我们更好的理解模型
nthread 用来进行多线程控制,默认为最大可能的线程数(使用CPU全部的核)
eta 和GBDT种的 learning rate 类似,通过减少每一步的权重可以提高模型的鲁棒性 典型值:0.01~0.02
min_chile_weight 默认为1 决定最小叶子节点样本权重和,类似 GBDT的min_child_leaf(最小样本总数), 这个参数用于避免过拟合,值越大,可以避免模型学习到局部的特殊样本,但如果这个值越高会导致欠拟合,可以使用CV调优
max_depth 默认6 树的最大深度 可以使用CV调优 典型值:3~10
max_leaf_nodes 树上最大的节点或叶子数量,可以替代max_depth的作用,因为如果生成二叉树,一个深度为n的树最多n2个叶子,如果定义这个参数模型会忽略max_depth
gamma 默认0,在节点分裂时,只有分裂后损失函数的值下降了 才会分裂这个节点,gamma制定了节点分裂所需的最小损失函数下降值。这个参数越大算法越保守,可使用CV调整,和损失函数息息相关。
max_delta_step 默认0,限制每棵树权重改变的最大步长,如果为0意味着没有约束,如果被赋予正值会让算法更加保守, 通常不设置。(各类样本十分不平衡时可以尝试)
subsample 默认1,控制每棵树随机采样的比例,减小这个参数的值,算法会更加保守,避免过拟合,(如果设置过小,会欠拟合)典型值0.5~1
colsample_bytree 默认1,控制每棵随机采样的列数的占比 典型0.5~1
colsample_byleve 默认1,控制树的每一集的每一次分裂,对列数的采样的占比,一般不调整
lambda 默认1,权重的L2正则化项,(和Ridge类似),可以应用在很高维度的情况下使得算法的速度更快
-
scale_pos_weight 默认1,在个类别十分不平衡是,把这个参数设置为正数,可以使得算法更快收敛。
... ...
bagging 套袋
关注降低方差:度量了同等大小的训练集的变动导致学习性能的变化。刻画了数据扰动所导致的影响。
通过对训练样本重新采样的方法得到不同的训练样本集,在这些新的训练样本集上分别训练学习器,最终合并每一个学习器的结果,作为最终的学习结果。
随机森林
from sklearn.ensemble import RandomForestClassifier
确定森林中的树是 CART 二叉树
样本随机: 从样本中随机有放回的抽取 n 个样本(样本有重复)
特征随机: 从所有的属性中随机选取 k 个属性, 选择最佳的分割属性作为节点建立决策树
重复以上步骤 m 次, 即建立 m 棵CART决策树
-
这 m 棵CART树形成随机森林, 通过投票表决结果, 决定数据属于哪一类
投票机制: 一票否决、 少数服从多数、 加权
模型调参:
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini', max_depth=None, max_features='auto', max_leaf_nodes=None, min_impurity_split=1e-07, min_samples_leaf=1, min_samples_split=2, min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1, oob_score=True, random_state=10, verbose=0, warm_start=False)
---------------------
- 选取 K 值
- 设置最大深度(一般不超过8)
- 棵数
- 最小分裂样本数
- 类别比例
无监督学习
聚类
K-means * from sklearn.cluster import KMeans
-
算法步骤
在整个样本群中定义 K 个种子点、
分别计算每个样本点到所有种子点的欧式距离, 标记最小的距离为该种子点代表的簇
当所有样本点类簇的归属全部划分完成后, 把每一个种子点移动到其所代表的那个类簇点群的几何中心
重复 2 3 两步, 直至所有的种子点不需要在移动为止
KMeans(algorithm='auto', copy_x=True, init='k-means++', max_iter=300,n_clusters=8,
n_init=10, n_jobs=None, precompute_distances='auto',random_state=None,
tol=0.0001, verbose=0)
训练过程: 根据 K-means++ 选取 8 个种子点, 计算所有样本点到每一个种子点的欧氏距离, 取这个样本点距离最近的那个种子点, 该样本点就划归为这个种子点的簇。将种子点移动到该簇的几何中心, 再循环上面的操作, 直至种子点不再移动为止。 最后得到八个有序号的簇(不是标签, 因为多次训练序号可能会发生改变)
预测 km.predict(digits_x_train) 得到的是所属的簇的序号
digits_y_pre = km.predict(digits_x_test) 预测的簇的序号
</pre>
-
ARI 指标, 适用于有对应的标签数据(聚类问题一般没有标签数据), 代表的是聚类的划分和标签的划分的吻合程度
from sklearn.metrics import adjusted_rand_score
adjusted_rand_score(digits_y_test, digits_y_pre)
-
轮廓系数: 用于评测聚类划分的性能, 兼顾了聚类内部的凝聚程度和聚类之间的离散程度
from sklearn.metrics import silhouette_score
样本轮廓系数的平均数输出聚类的编号
labels = km.labels_
silhouette_score(digits_x_train, labels)
寻找最优聚类个数
clusters = [2,3,4,5,6,7,8,9,10]
scores = []
for cluster in clusters:
km = KMeans(n_clusters=cluster)
km.fit(digits_data)
labels = km.labels_
score = silhouette_score(digits_data, labels)
scores.append(score)
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(clusters, scores)
plt.show()</pre>
聚类算法有多种: 中心聚类,关联聚类,密度聚类,概率聚类,降维,圣经网络/深度学习
数据升维
多项式特征生成器
from sklearn.preprocessing import PolynomialFeatures
特征降维
PCA *
from sklearn.decomposition impoprt PCA
在数据挖掘的过程中, 某些属性之间存在相关性, 可以抹去或者通过某些算法把他们映射到更低的维度, 从而提高机器学习的效率和准确率。
-
向量的内积和投影
-
内积:两个维度(特征个数)相同的向量
(a1, a2, ... ... ,an)^T 和 (b1, b2, b3, ... ... , bn) ^T
(a1, a2, ... ... ,an) * (b1, b2, b3, ... ... , bn) ^T = a1b1 + a2b2 + ... ... + anbn
-
向量内积的几何意义:
二维空间中有两个向量 A(x1, y1), B(x2, y2)
|A|*cosα 为 A 向量 在 B 向量上的投影
A * B = |A| * |B| * cosα 为内积
此时如果 B 为单位向量 那么 A * B = |A| * cosα 为 A 在 B 上的投影
-
向量基
在一个平面直角坐标系中, 表示某个点P(x0, y0) 此时向量P值就是(x0, y0)
x轴y轴上个存在一个模为1的向量(1, 0) 和 (0, 1) 称(1, 0) , (0, 1) 为二维空间中的一组基
只要是两个线性无关的单位向量都可以作为整个空间的一组基
一般情况下, 我们有m个n维向量, 像将其转换成R个由N维向量构成的新空间, 首先将R个基 按照行进行排写成一个矩阵A , 再将向量按照列组合成一个矩阵B, 然后计算 A * B
两个矩阵相称的物理意义: 实际上就是将右边的矩阵的每一个列转变到左边矩阵为基的一个新的空间中
右边矩阵的行数代表降维之前的维度, 左边矩阵的行数代表降维以后的维度。
问题: 如何选择最优基?
-
-
Principal Component Analysis 主成分分析
[[1, 1, 2, 4, 2], [1, 3, 3, 4, 4]]
-
让每一个特征减去这个特征上所有值的平均值
[[-1, -1, 0, 2, 0], [-2, 0, 0, 1, 1]]
-
求去平均值以后的矩阵的协方差
方差: 每个样本与均值的差的平方和除以样本个数
协方差: Cov = (1/m)X*X^T = 1/5([6, 5], [4, 6])
-
求协方差矩阵的特征值及其对应的特征向量
|C - λE| = 0 ====> |[6/5 - λ 4/5], [4/5 6/5 - λ]|
解得 λ = 2, 2/5即协方差矩阵C的特征值
对应的特征向量依次是
特征向量标准化
把特征向量组成一个特征矩阵
验证矩阵的对角化
将特征值按照从大到小的顺序排列, 取前K个特征值对应的特征向量, 就构成了K维的主成分空间即 P
降维, 对 Y 向量降维, X = PY , X 就是 Y 的K维主成分空间
-
SVD矩阵分解
LDA
独立成分分析(ICA)
与PCA相关, 但他在发现潜在因素方面效果良好,它可以应用在数字图像、当问数据库、经济指标、心理测量等
SMOTE
针对类不均衡的过采样算法
对于少数类的每一个样本x, 以欧氏距离标准计算他到少数类样本集中的所有样本的距离, 得到其K近邻
根据样本不均衡比设置一个采样比例以确定采样倍率, 对于每一个少数类样本x, 其K近邻中随机选择若干个样本, 假设选择的近邻为Xn
-
对每一个随机选出的近邻Xn, 分别与原样本按如下公式构建新的样本
Xnew = X + rand(0, 1) * |x - xn|
from imblearn.over_sampling import SMOTE
smote = SMOTE()
target.value_counts() # 观察是否存在样本不均衡问题
data, target = smote.fit_sample(data, target)
# 通过以上过采样算法后 (target==0).sum() 与 (target==1).sum() 数量一样多</pre>
缺陷:
K值选择存在盲目性
无法克服非均衡数据集的数据分布问题, 易产生分布边缘化问题, 因为负类样本决定了其紧邻的可选择位置, 会造成人造样本越来越边缘化, 是的边界模糊加大算法分类难度。
预处理
特征工程: 筛选有用的特征
清洗: 缺失值, 异常值, 重复值
数据处理
- 数据的归一化: 将属性缩放到一个指定的最大值和最小值之间 通常是(0, 1)
from sklearn.preprocessing import MinMaxScaler
MinMaxScaler().fit_transform(data)
# (data-min(data)) / max(data) - min(data)</pre>
目的:
- 对于方差较小的属性可以增加其稳定性,
- 维持稀疏矩阵中0的条目,
- 防止过大的属性对模型起过份主导作用
- 数据的标准化
将数据按照比例进行缩放, 使之落入一个小的特定区间, 标准化以后的数据可正可负
from sklearn.preprocessing import StandardScaler
StandardScaler().fit_transform(data)
# (data - data.mean())/ data.std() 服从标准正态分布</pre>
- 数据的正则化
from sklearn.preprocessing import Normalizer
Normalizer().fit_transform(data)
# 默认为L2正则化</pre>
模型评测指标
每个模型都自带有一个性能检测方法, score
在性能检测过程中会把 data 带入模型中进行训练并得到预测值, 然后求预测值和 target 的吻合程度(准确度, 从宏观上表达了预测数据和真实数据的差别)
性能检测报告
栗子:有两个类别 A 和 B 预测结果有4种 TrueA,TrueB,FalseA,FalseB
精确率: 表示每一个类别预测正确的数量占预测为该类别的数量的比例
Preision_A = TrueA/(TrueA+FalseA),Preision_B = TrueB/(TrueB+FalseB)
召回率: 表示每一个类别预测正确的数量占真正为该类别的数量的比例
Recall_A = TrueA/(TrueA+FalseB)
F1指标: 精确率和召回率的调和平均数, 如果两个指标相近,那么调和平均数的值就大
F1_A = 2/(1/Precision_A + 1/Recall_A)
【注意】在评测一个模型的时候如果某个标签精确率和召回率偏差过大,则该模型在预测该类别的时候的预测结果就不具备参考价值
-
分类问题: 混淆矩阵
from sklearn.metrics import classification_report
print(classification_report(y_pre, y_test))
-
回归问题: 均方误差 平均绝对误差
from sklearn.metrics import mean_absolute_error,mean_squared_error
mean_absolute_error(y_,b_y_test)
mean_squared_error(y_,b_y_test)
交叉验证
from sklearn.model_selection import cross_val_score
# 实例化算法模型
knn = KNeighborsClassifier()
dt = DecisionTreeClassifier()
# 输出划分对应类别时的准确率
cross_val_score(dt, data, target)
cross_val_score(knn, data, target)
# 根据需求选取更适合的算法</pre>
网格搜索算法参数调优
from sklearn.model_selection import GridSearchCV
# K近邻分类模型
GridSearchCV(knn,param_grid={"n_neighbors": [i for i in range(1, 21)]})
# 岭回归模型
GridSearchCV(ridge,param_grid={"alpha": [10**i for i in range(-20, 6)]})
# 逻辑斯蒂分类模型
GridSearchCV(lgs,param_grid={"C":[10**i for i in range(-3, 2)]})
# 梯度下降模型 可以调节学习率 alpha
# 决策树模型 通过调节 max_depth 最大深度
# 支持向量机
GridSearchCV(svc,param_grid={"C":[0.5,1.0,3,5,2],"kernel":["poly","rbf"],"gamma":[0.1,0.2,0.5,1,2]})
'''
C惩罚参数(惩罚参数越大,惩罚程度越大, 容错率越小)
kernel,核函数,决定模型是线性还某种非线性,linear、rbf、poly、sigmoid、precomputed 例如rbf核函数:exp(-gamma|u-v|^2) sigmoid核函数:1/(1+ e^(-gamma*Z))
gamma,即是核函数的参数值,默认是auto,则选择1/n_feature
'''
gsc.best_estimator_ # 最优参数组合的模型</pre>