…
数据与科学计算 Anaconda 下载地址
配置清华源,打开Anaconda Prompt
1 2 conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ conda config --set show_channel_urls yes
或修改user文件夹下的.condarc文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 channels: - defaults show_channel_urls: true channel_alias: https://mirrors.tuna.tsinghua.edu.cn/anaconda default_channels: - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/pro - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2 custom_channels: conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
运行命令清除缓存
Tensorflow 创建虚拟环境。
1 conda create -n test_env python=3.7
创建完成后,在开始菜单->Anaconda3—>Anaconda Navigator
中可以看到创建完成的环境。
在Anaconda Prompt中启动虚拟环境
安装CPU版Tensorflow
1 conda install tensorflow -i https://pypi.tuna.tsinghua.edu.cn/simple/
搜索安装GPU版
1 2 conda search tensorflow-gpu conda install tensorflow-gpu=1.15.0
Tensorflow与CUDA版本对应
版本
CUDA
1.2 - 1.4
8.0
1.5 - 1.12
9.0
1.13 - 1.15
10.0
2.0
10.0
2.1
10.1
PyTorch 安装PyTorch
1 conda install pytorch torchvision cudatoolkit=10.1 -c pytorch
离线安装方式,安装包下载 或官方下载
1 conda install --offline pytorch-1.5.0-py3.7_cuda101_cudnn7_0.tar.bz2
或到安装目录下C:\Users\xxx\anaconda3\pkgs
替换安装包。
数据分析与可视化 安装环境:
编辑requirements.txt
文件,安装依赖。
1 2 3 4 5 6 7 matplotlib==2.2.2 # 画图工具 numpy=1.14.2 # 运算工具 pandas==0.20.3 # 数据处理工具 TA-Lib==0.4.16 # 技术指标库 tables==3.4.2 # 读取 hdf5 jupyter=1.0.0 # 展示数据平台 pip install -r requirements.txt
Jupyter Notebook 原名Ipython Notebook,是一个基于Web的Python IDE,支持Julia,Python,R三种语言,在画图、数据展示方面非常方便。
运行Jupyter:
默认在http://localhost:8888打开IDE。
Cell:一对In Out称为Cell。有编辑模式和命令模式,类似与Vim。
编辑快捷键:
Shift + Enter:执行,并下移
Ctrl + Enter:执行,不移动
命令快捷键:
A:在上方添加Cell
B:在下方添加Cell
D + D:删除Cell
Markdown:在上方改为标记。
Matplotlib Matplotlib是用来开发2D,3D图表的工具。可以参考Echarts。
1 2 3 4 5 6 7 8 9 10 import matplotlib.pyplot as plt # 魔法函数:仅仅在IPython中使用,此句表示可以内嵌绘图,并且可以省略掉plt.show()这一步。 %matplotlib inline plt.figure() plt.plot( [1, 0, 8], # 横坐标 [4, 2, 6] # 纵坐标 ) plt.show()
Matplotlib有三层结构:
容器层:提供画板(Canvas),画布(Figure)以及绘图区/坐标系(Axes,SubPlot)。
辅助显示层:显示图例,刻度,网格等内容。
图像层:显示图像的内容。
常用方法有:
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 # 定义数据 x = range(10) y = [random.uniform(10, 20) for i in x] # uniform 均匀分布 x_labels = [f"11:{i:02}" for i in x] # 设置步长为 5 y_labels = range(40) u = range(10) v = [random.uniform(40, 50) for i in x] # 创建画布 容器层 plt.figure( figsize=(20, 8), # 图像的尺寸 dpi=300 # 图像的DPI ) # 创建折线图 图像层 plt.plot(x, y) # 添加坐标轴刻度 plt.xticks(x[::5], x_labels[::5]) plt.yticks(y[::5]) # 添加网格 plt.grid( True, # 是否显示 linestyle='--', # 形状 alpha=0.3 # 透明度 ) # 添加标题 plt.xlabel("Time") plt.ylabel("Temp") plt.title("The Plot") # 添加多条曲线 图像层 plt.plot(u, v, color="r", linestyle="--", label="CN") # 图例,要求plot必须设置label属性 plt.legend(loc="lower left") # 显示位置 # 保存图像 plt.savefig(path) # 显示图像,并释放资源 plt.show()
如果绘制多个图像:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 设置 1 x 2 的绘图区,用法类似于plot figure, axes = plt.subplots(nrows=1, ncols=2) axes[0].plot(x, y) axes[1].plot(u, v) axes[0].legend() axes[1].legend() axes[0].grid(True) axes[1].grid(True) axes[0].set_xticks() axes[1].set_xticks() axes[0].set_xlabel() axes[1].set_xlabel()
也可以画其他图像。
散点图(scatter):观察数据的分布规律
柱状图(bar):统计对比数据 单柱:
1 2 3 4 plt.bar(x, y, width=0.5, # 柱状图宽度 align='center', # 对齐方式 )
多柱:
1 2 3 4 5 6 7 8 plt.bar(x, y1, width=0.2, # 柱状图宽度 align='center', # 对齐方式 ) plt.bar([i+0.1 for i in x], y2, width=0.2, # 柱状图宽度 align='center', # 对齐方式 )
直方图(histogram):反应一组连续数据的分布
组数 = 极差 / 组距 = (max - min) / bins
1 2 3 4 5 6 7 8 9 distance = 3 bins = (max(x) - min(x)) // distance plt.hist(x, bins=bins, density=True # 是否显示频率 ) plt.xticks(range(min(x), max(x) + 2, distance))
饼图(pie):分类数据的占比情况
1 2 3 4 5 6 plt.pie(x, labels=bins, # 每部分名称 autopct="%1.2f%%" # 占比显示格式 ) plt.axis('equal') # 变圆 plt.legend()
如果无法正常显示中文,可以增加配置:
1 2 plt.rcParams['font.sans-serif']=['SimHei'] #解决中文显示 plt.rcParams['axes.unicode_minus'] = False #解决符号无法显示
或是一劳永逸的(Windows):
删除/.matplotlib/下的缓存文件; 新增/.matplotlib/matplotlibrc配置文件,修改内容为:
1 2 3 4 backend:TkAgg font.famly: sans-serif font.sans-serif: SimHei axes.unicode_minus: False
Numpy Numpy 是一款高效的运算工具,用于快速处理任意维度的数据。
ndarray 数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 score = np.array([ [1, 2, 3], [4, 5, 6] ]) # ndarray 类型,2维 score = np.array([ [ [1, 2, 3], [4, 5, 6] ], [ [1, 2, 3], [4, 5, 6] ] ], dtype=np.int32) # 3维,,32位int
ndarray在底层使用C语言编写,内部解除了GIL,因此效率大大增加。ndarray因此也支持了向量化运算。
ndarray 包含了几种属性:
ndarray.shape:数组维度的元组(“m行n列”等描述)
ndarray.ndim:数组维度
ndarray.size:元素数量
ndarray.itemsize:每个元素的长度
ndarray.dtype:元素类型,如np.bool,np.int32,np.uint16,np.float64,np.complex64,np.object,np.string,np.unicode等
数组操作 数组的生成:
1 2 3 4 5 6 7 8 9 10 11 # 全0数组,也可以加dtpye,order参数 np.zeros(shape) # 全1数组 np.ones(shape) # 现有数组生成 np.array(list) # 深拷贝数组 np.copy(a) # 深拷贝数组 np.asarray(a) # 浅拷贝数组 # 生成固定范围的数组 np.linspace(0, 100, 7) # 0到100,7个数,闭区间 np.arange(0, 100, 7) # 0到100,步长7,左闭右开
随机数生成:
1 2 3 4 5 6 7 8 # 均匀分布,返回0~1的一组均匀分布的数 np.random.rand() # 均匀分布,从[low,high)中随机采样,size指定输出样本数目,可以是int或元组 np.random.uniform(low, high, size=None) # 标准正态分布,获取一个或多个样本 np.random.randn() # 正态分布,loc为均值,scale为标准差 np.random.normal(loc, scale, size=None)
数组操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # 定义 data = np.array([ [1, 2, 3, 4], [10, 20, 30, 40], ]) # 选择元素:二维数组,选择第一行的前三个 data[0, 0:3] # 切片操作为左闭右开 # 改变形状:重新分割数据,并返回 data.reshape(shape) # 改变形状:直接改变原始数据 data.resize(shape) # 数组转置 data.T() # 类型修改 data.astype("int32") # 序列化 data.tostring() # 去重 np.unique(data) # 一维化 data.flatten()
数组运算:
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 # 逻辑运算: res = data > 2 # 对每一个数字做计算并返回结果 data[data > 2] # 返回满足条件的部分数据 data[data > 2] = 1.9 # 对满足条件的数据做运算 np.all() # 如果全部是True就返回True np.any() # 如果有True就返回True np.where(condition, a, b) # 满足condition的元素置为a,否则置为b condition = np.logical_and(con_a, con_b) # 条件与运算 condition = np.logical_or(con_a, con_b) # 条件或运算 # 统计运算: np.min(data, axis=-1) # axis 表示按行还是按列 np.max(data, axis=-1) np.median() # 中位数 np.mean() # 均值 np.std() # 标准差 np.var() # 均方差 std 的平方 np.sum() np.argmax(data, axis=1) # 返回最大值索引 # 数组间运算,要遵循广播机制 data + 1 # 对每一个元素运算 data1 * data2 # 对应元素运算 # 矩阵运算,此处的矩阵必须是二维数组 mt = np.mat(data) # 转化为矩阵 # 矩阵乘法 np.matmul(mt1, mt2) np.dot(mt1, mt2) mt1 * mt2 # 数组合并 np.hstack((a, b)) # 水平拼接 np.vstack((a, b)) # 垂直拼接 np.concatenate((a, b), axis=0) # 任意拼接,需要设置轴 # 数组分割 np.split(x, 3) # 按个数分割 np.split(x, [1, 3, 5]) # 按索引分割
IO操作 读取数据:
1 2 3 4 5 6 7 # 无法读取字符串 data = np.genfromtxt("data.csv", delimiter=',') # 处理缺失值:直接删除缺失值,插值处理缺失 # 获取缺失值个数 nan_num = np.count_nonzero(data[:, i][t[:, i] != t[:, i]]) # 判断缺失 np.isnan(i)
GPU 加速 首先需要CUDA
,CUDNN
,可以到官网下载。
查看本机CUDA情况可以到控制面板
->NVIDIA控制面板
->帮助
->系统信息
->组件
里面查看。
通过使用Visual Studio可以开发CUDA应用,例如查看一个NVIDIA CUDA的例子: 使用Visual Stuido打开项目:CUDA安装目录->Samples,配置1_Utilities->deviceQuery->右键设置为启动项目,执行,就可以看到CUDA信息了。
安装 cupy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # For CUDA 8.0 pip install cupy-cuda80 # For CUDA 9.0 pip install cupy-cuda90 # For CUDA 9.1 pip install cupy-cuda91 # For CUDA 9.2 pip install cupy-cuda92 # For CUDA 10.0 pip install cupy-cuda100 # For CUDA 10.1 pip install cupy-cuda101 # Install CuPy from source pip install cupy
使用方法同numpy一样:
1 2 3 4 5 6 7 8 9 10 11 12 import numpy as np import cupy as cp # numpy 用法 x=np.ones((1024,512,4,4))*1024. y=np.ones((1024,512,4,1))*512.3254 for i in range(20): z=x*y # cupy 用法 x=cp.ones((1024,512,4,4))*1024. y=cp.ones((1024,512,4,1))*512.3254 for i in range(20): z=x*y
Pandas Pandas 也是处理数据的工具。拥有便捷的数据处理能力,读取文件也方便,同时很好的的结合了matplotlib。
DataFrame 尽管numpy在数据计算方面较python原始的方法有很大优势,但是同时也缺失了数据含义的展示。因此DataFrame在这方面进行了增强。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import numpy as np import pandas as pd # 添加行列索引 row_labels = [f"第{i:02}" for i in range(10)] # 或使用日期 col_labels = pd.date_range(start="20200101", period=5, freq="B") data = pd.DataFrame(np.random.normal(0, 1, (10, 5)), index=row_labels, # 行索引 colums=col_labels # 列索引 ) # 正态分布
常用属性有:
1 2 3 4 5 data.shape data.index # 必须批量修改索引 data.columns data.values # 去除索引后的数据,ndarray data.T
常用方法:
1 2 3 4 5 6 7 8 head() # 返回前几行 tail() # 返回后几行 reset_index(drop=True) # 重置索引 set_index("字段名", drop=True) # 单个索引 set_index(["字段1", "字段2"], drop=True) # 多个索引 # 对于多级索引还有属性: data.index.names data.index.levels
Panel (即将弃用) 是DataFrame的容器,是存储三维数据的结构。
1 2 3 4 5 6 7 8 9 10 11 pdata = pd.Panel( np.arange(24).reshape(4, 3, 2), items=list("ABCD"), major_axis=pd.date_range("20200101", period=3), minor_axis=['1', '2'] ) # 查看某一组数据 pdata['A'] pdata.major_axis("") pdata.minor_axis("1")
Series Series 是带索引的一维数组。
创建Series
1 2 3 4 5 6 # 数组 sr = pd.Series(np.arange(10), index=[...]) # 或字典 sr = pd.Series({'a': 1, 'b': 2, 'c': 3}) # 或已有数据 sr = data.iloc[1, :]
常用属性有:
数据操作 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 # 直接索引,先列后行 data["字段"]["记录"] # 按名索引 data.loc["记录"]["字段"] data.loc["记录", "字段"] # 按数字索引 data.iloc[1][2] # 混合索引 (即将弃用) data.ix[0:4, ["字段1", "字段2"]] # 赋值 data["字段"] = 100 # 按列 data.loc["记录", "字段"] = 100 # 单个 # 排序 data.sort_values(by="字段", ascending=False) data.sort_values(by=["字段1", "字段2"], ascending=False) data.sort_index() # 算数运算 data["字段"] + 3 data["字段"].add(3) # 逻辑运算 data[data["字段"] > 2] data[(data["字段"] > 2) & (data["字段"] < 10)] data.query("字段 > 2 & 字段 < 10") data[data["字段"].isin([100, 50])] # 统计运算 min max mean median var std describe() # 获取每个字段的所有统计指标 idxmax() # max的索引 idxmin() # 累计统计函数,查看走势 cumsum() cumsum().plot() # 顺便画图 cummax() cummin() cumprod() # 自定义运算 apply(func, axis=0) # 按列删除 data.drop(["字段"], axis=1)
绘图 绘图函数如: DataFrame.plot() Series.plot()
1 2 # kind 参数,图像类型 plot(x="字段1", y="字段2", kind="scatter")
IO操作 读取数据,且可以识别表头等,支持CVS,JSON,HTML,Execl,HDF5,SQL等。
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 # 读取CVS data = pd.read_csv( path, usecols=['字段1', '字段2'], names=["字段名1", "字段名2"] ) # 存储CSV data.to_csv( path, columns=['字段'], header=True, # 是否写入表头 mode="wa", # 写模式 index=True # 是否写入索引 ) # 读取HDF5 data = pd.read_hdf( path, key=['字段'] ) # 存储HDF5 data.to_hdf( path, key=['字段'] ) # 读取JSON data = pd.read_json( path, orient="records" # 读入的形式,读入成记录 lines=True # 每一行是否有换行 ) # 存储JSON data.to_json( path, orient="records" lines=True )
处理缺失值 当缺失的值为NAN时:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 判断是否有Null pd.isnull(data) pd.isnull(data).any() # 列出所有字段是否缺失 pd.notnull(data) pd.notnull(data).all() # 将所有缺失值置0 data[pd.isnull(data)] # 删除有缺失值的样本 inplace 是否修改原始 DataFrames dropna(inplace=False) # 替换缺失 fillna(value, inplace=False) # 均值替换 fillna(data['字段'].mean(), inplace=False)
当缺失值为其他形式:
1 2 # 替换 replace(to_replace="?", value=np.nan)
数据离散化 通过对数据分类,并按分组分别统计处理数据。 方式:one-hot编码(哑编码)
1 2 3 4 5 6 7 8 9 10 # 分组 # 自动分组 sr = data.qcout(data, bins) # 自定义分组,给定边界 sr = data.cut(data, [10, 20, 30]) # 编码 get_dummies(sr, prefix='') # 查看每个分组的情况 sr.value_counts()
合并 1 2 3 4 # 按位置拼接,如果按列拼接,要字段一致 pd.concat([data1, data2], axis=1) # 按索引合并,on 索引,inner 内连接 pd.merge(left, right, how='inner', on=['字段1', '字段2'])
交叉表与透视表 用于探索两个变量的关系。
交叉表:用于查看两列数据之间的关系
1 pd.crosstab(data['字段1'], data['字段2'])
透视表:也是用于查看两列数据之间的关系
1 pivot_table(data['字段1'], data['字段2'])
分组与聚合 1 2 3 # 根据字段1分组,根据字段2聚合 data.groupby(by="字段1")['字段2'].max() data['字段2'].groupby(col["字段1"]).max()
SFrame Scipy Scikit-Learn Python 数据分析 步骤
获取数据
探索分析,可视化
预处理
分析建模
模型评估
获取数据 手段
数据仓库:与数据库面向业务不同,数据仓库基于主题记录,是为了数据分析服务。
检测与抓取:爬虫解析网页。
urllib / urllib2 / requests / scrapy
PhantomJS / beautifulSoup / Xpath - 解析 DOM,执行JavaScript
填写,埋点,日志:
填写:用户填写的信息
埋点:跟踪用户使用情况(页面停留时间,跳出率),用于复现用户的操作过程。
日志:前端日志、后端日志。
计算:通过已有数据生成的衍生数据
数据集
Kaggle & 天池
ImageNet / Open Images
统计局、政府机构、公司财报
单因子数据分析 Pandas 读取数据
1 2 3 import pandas as pd df = pd.readcsv("") df.head(10)
偏态:中位数与均值有差别。 S = (1/n) * sum((xi - xp)^3) / ((1/n) * sum((xi - xp)^2))^(3/2)
峰度:数据集中程度的衡量。正态分布是K = 3,一般低于1或大于5则不是正态分布。 K = (1/n) * sum((xi - xp)^4) / ((1/n) * sum((xi - xp)^2))^2
三大分布:卡方、t分布、F分布。
抽样理论:误差、精度、抽样数量。下面两种情况的计算公式不一样。
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 df["col"].mean() # 均值 df["col"].median() # 中位数 df["col"].quantile(q=0.25) # 分位数 df["col"].mode() # 众数,可能有多个 df["col"].std() # 标准差 df["col"].var() # 方差 df["col"].sum() # 求和(或字符串相连) df["col"].skew() # 偏态系数(负数是右偏,正数左偏) df["col"].kurt() # 峰态系数(负数是比正态平缓,正数比正态尖凸) import scipy.stats as ss # 正态分布 mvsk = (均值,方差,偏态,峰态) ss.norm.stats(moments="mvsk") # 概率密度函数 ss.norm.pdf() # 概率分布函数的反函数,输入 (0, 1) ss.norm.ppf() # 概率分布函数 ss.norm.cdf() # 得到符合正态分布的数字 ss.norm.rvs(size=10) # F 分布 ss.f # T 分布 ss.t # 抽样 df.sample(n=10) # 抽10个 df.sample(frac=0.01) # 抽 1%
数学分类
定类数据:无序,离散。数值化处理。
定序数据:有序,可比大小,离散。数值化处理。
定距数据:连续,可求差值,比大小,但没有绝对零点。例如温度,不能说谁比谁温度高几倍。归一化处理。
定比数据:连续,可求差值,比大小,有绝对零点,可求比值
单属性分析
异常值分析:
连续异常值:取四分位数 Q1 Q2 Q3,则区间范围 (Q1 - k * (Q3 - Q1), Q3 + k * (Q3 - Q1)) 外的算异常值。k通常取值为 (1.5, 3)。异常值可能会让一系列数据失效。一般舍弃或取边界值代替。
离散异常值:定义范围以外的值。一般舍弃或用特殊标记处理。
知识异常值:不符合常理的值。
对比分析:
绝对数比较:成绩,身高
相对数比较:
结构相对数:产品合格率,考试通过率
比例相对数:三大产业比例
比较相对数:不同时期下的某商品价格
动态相对数:用户数量增速
强度相对数:人均GDP,粮食亩产
比较方法:
时间维度
空间维度
经验与计划的比较:例如失业率达到某值就会社会动荡
结构分析:分析部分与总体之间的关系
分布分析:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import numpy as np import pandas as pd df = pd.read_csv() # 检查去除异常值 df[df["satisfaction_level"].isnull()] df = df.dropna() # df = df.dropna(axis=0, how="any") # axis = 0 行 1 列 # df = df.fillna() # 直方图 sl = df["satisfaction_level"].dropna() np.histogram(sl.values, bins=np.arange(0, 1.1, 0.1)) # (0, 1.1) 之间,间隔 0.1
处理连续异常值
1 2 3 4 5 6 le = df["last_evaluation"] q_low = le.quantile(q=0.25) q_high = le.quantile(q=0.75) q_interval = q_high - q_low k = 1.5 le = le[le < q_high + k * q_interval][le > q_low - k * q_interval]
查看离散值峰度
1 2 3 pj = df["number_projcet"] pj.value_counts() pj.value_counts(normalize=True).sort_index()
数据分段
1 2 pj.value_counts(bins=10) # 左开右闭 pj.histogram(sl.values, bins=10) # 左闭右开
分组聚合
1 2 3 df.groupby("department").mean() df.loc[:, ['last_evaluation', 'department']].groupby("department").mean() df.loc[:, ['average_monthly_hours', 'department']].groupby('department')['average_monthly_hours'].apply(lambda x: x.max() - x.min())
可视化 常用库
matplotlib
seaborn
plotly
条形图、柱状图:观察离散值
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 import matplotlib.pyplot as plt %matplotlib notebook # Jupyter notebook 使用 # %matplotlib inline # 设置图像风格 sns.set_style(style='darkgrid') plt.title('Salary') plt.xlabel('salary') plt.ylabel('count') plt.xticks( np.arange(len(df['salary'].value_counts())) + 0.5, # +0.5 使其右移 df['salary'].value_counts().index ) plt.axis([0, 4, 0, 10000]) plt.bar( np.arange(len(df['salary'].value_counts())) + 0.5, df['salary'].value_counts(), width=0.5 ) # 添加标注 for x, y in zip(np.arange(len(df['salary'].value_counts())) + 0.5, df['salary'].value_counts()): # Label (x, y) 坐标,标注的值,水平位置,垂直位置 plt.text(x, y, y, ha='center', va='bottom') sns.countplot(x='salary', data=df) # sns.countplot(x='salary', hue='department', data=df) plt.show()
直方图:观察连续值
1 2 3 4 5 6 7 8 9 df = df.dropna() f = plt.figure() f.add_subplot(1, 3, 1) sns.histplot(df['satisfaction_level'], bins=10, kde=True) f.add_subplot(1, 3, 2) sns.histplot(df['last_evaluation'], bins=10, kde=True) f.add_subplot(1, 3, 3) sns.histplot(df['average_monthly_hours'], bins=10, kde=True) plt.show()
箱线图:上界、下界、四分位数
1 2 3 4 sns.boxplot(y=df['time_spend_company']) # 竖着 plt.show() sns.boxplot(x=df['time_spend_company'], saturation=0.75, whis=3) # 横着 plt.show()
折线图:数据变化走势
1 2 3 4 sub_df = df.groupby('time_spend_company').mean() # sns.pointplot(sub_df.index, sub_df['left']) sns.pointplot(x='time_spend_company', y='left', data=df) plt.show()
饼图:结构分析
1 2 3 4 5 6 7 8 9 10 lb = df['department'].value_counts().index explodes = [0.1 if i == 'sales' else 0 for i in lb] # 间隔 plt.pie( df['department'].value_counts(normalize=True), labels=lb, autopct="%1.1f%%", colors=sns.color_palette("Reds"), explode=explodes ) plt.show()
其他方案:
多因子数据分析 假设检验:根据假设条件,从样本推断总体,或推断样本与样本之间的关系。
原假设 H0 符合某个分布
备择假设 H1 不符合该分布
检验统计量:用于判断是否符合某个分布
显著性水平:确定拒绝域 (取0.05)
最后计算P值,或样本统计值,做出判断(P > 0.05 接受)
检验方法
u 检验:检验是否复合正态分布
卡方检验:检验两个因素之间是否有比较强的联系
T 分布检验:分布是否一致
F 检验(方差检验):多样本,两两之间是否有差异
SST 整体的方差
SSM 组间平方和:每组与整体均值的平方和
SSE 组内平方和:数据与组内的均值的平方和
F = (SSM / (m - 1)) / (SSE / (n - m))
相关系数
Pearson 皮尔逊相关系数:因变量与自变量的相关性
Spearman 斯皮尔曼相关系数:跟名次有关,适合相对的比较
线性回归:分析两变量之间定量关系。
效果判定:决定系数(一元),残差不相关(多元),DW 检验(范围(0, 4),好的回归 DW=2)
主成分分析:提取区分度大的维度
求特征协方差矩阵
求特征值,特征向量
取最大的k个特征值
重新投影样本点到特征向量上
奇异值分解:一种PCA方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 import numpy as np import scipy.stats as ss # 产生20个符合正态分布的数据 norm = ss.norm.rvs(size=20) # 检查是否符合正态分布(采用偏度和峰度方法)得到 检验统计量的值 和 P值 ss.normaltest(norm) # 卡方 检验统计量的值 P值 自由度 理论分布 ss.chi2_contingency([[15, 95], [85, 15]]) # T分布 检验统计量的值 P值 ss.ttest_ind(ss.norm.rvs(size=10), ss.norm.rvs(size=20)) # 方差检验 ss.f_oneway([49, 50, 39, 40, 43], [28, 32, 30, 26, 34], [38, 40, 45, 42, 48])
通过QQ图方法判断一个分布是否与某已知分布重合。
1 2 3 4 5 6 7 from statsmodels.graphics.api import qqplot from matplotlib import pyplot as plt # 检验是否是正态分布 plt.show(qqplot( ss.norm.rvs(size=100) ))
计算相关性系数
1 2 3 4 5 6 7 8 9 10 # 构造数据 sa = pd.Series([1, 2, 11, 24, 13, 3, 5]) sb = pd.Series([5, 4, 12, 25, 11, 7, 1]) df = pd.DataFrame(np.array([sa, sb]).T) # 转化为两个列向量 # 求斯皮尔曼相关系数 sa.corr(sb, method='spearman') # 求皮尔逊相关系数 df.corr()
线性回归
1 2 3 4 5 6 7 8 9 10 11 from sklearn.linear_model import LinearRegression # 构造数据 x = np.arange(10).astype(np.float64).reshape((10, 1)) y = x * 3 + 4 + np.random.random((10, 1)) # 线性回归 reg = LinearRegression() res = reg.fit(x, y) y_pred = reg.predict(x) reg.coef_ # 斜率 reg.intercept_ # 截距
PCA 降维
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 from sklearn.decomposition import PCA # 构造数据 d = np.array([ np.array([2.5, 0.5, 2.2, 1.9, 3.1, 2.3, 2, 1, 1.5, 1.1]), np.array([2.4, 0.7, 2.9, 2.2, 3, 2.7, 1.6, 1.1, 1.6, 0.9]) ]).T # PCA 降维(奇异值分解) low = PCA(n_components=1) # 降到 1 维 low.fit(d) low.explained_variance_ratio_ # 保留的信息比例 low.fit_transform(d) # 降维后的数据 # 自定义 PCA def my_pca(data, n_components=1000): mean_vals = np.mean(data, axis=0) # 每个属性的均值 mid = data - mean_vals cov_mat = np.cov(mid, rowvar=False) # 按列求协方差 from scipy import linalg eig_vals, eig_vects = linalg.eig(np.mat(cov_mat)) # 求特征值,特征向量 eig_vals_index = np.argsort(eig_vals) # 获取排序后的下标 eig_vals_index = eig_vals_index[: -(n_components + 1): -1] eig_vects = eig_vects[:, eig_vals_index] # 取出特征向量 low_dim_mat = np.dot(mid, eig_vects) # 计算投影后的新矩阵 return low_dim_mat, eig_vals
复合分析
交叉分析:分析属性和属性之间的关系
分组分析:先分组再分析比较。一般与其他手段配合使用。
钻取:一种常用的分组手段,作用是改变数据维度的层次。分为向上钻取,向下钻取。
分组一般针对离散属性,对于连续属性则需要离散化。连续数据离散化:分割(一阶)、拐点(二阶)、聚类、不纯度(Gini系数)
相关分析
连续属性:直接计算
离散属性:
二类离散:皮尔逊相关系数、不纯度(Gini系数)
多类定序离散:可以编码为连续值,进行皮尔逊相关系数计算,但是会失真
熵:(单位:Bit)
条件熵
互信息:信息增益,条件熵相对于原来的熵减少的信息,对于分类数目多的特征,有不正确的偏向,不确定性是上不封顶的。 I(X, Y) = H(Y) - H(Y|X) = H(X) - H(X|Y)
熵的增益率:为了解决互信息上不封顶的特性而定,该值范围为 (0, 1)。但是该值不是对称的。 I(X, Y) / H(Y)
相关性:解决熵的增益率的对称问题。 corr(X, Y) = I(X, Y) / sqrt(H(X) * H(Y))
因子分析:从多个属性中分析共性的方法。
探索性因子分析:通过协方差矩阵、相关性矩阵分析,来转化、降维,得到最主要的因子。例如:主成分分析。
验证性因子分析:验证因子与关注的属性有什么关联。假设检验、回归分析等。
聚类分析
回归分析
交叉分析
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 # 获取数据 df = pd.read_csv('.\\data\\HR.csv') df = df.dropna() # 不同部门之间的离职率分布是否一致:T 分布检验 ind = df.groupby('department').indices sval = df['left'].iloc[ind['sales']].values # Sales 部门 tval = df['left'].iloc[ind['technical']].values # Technical 部门 ss.ttest_ind(sval, tval) # T 分布检查,检查是否有显著差异 # 所有部门之间的关系 key = list(ind.keys()) mat = np.zeros([len(key), len(key)]) for i in range(len(key)): for j in range(len(key)): p_val = ss.ttest_ind( df['left'].iloc[ind[key[i]]].values, df['left'].iloc[ind[key[j]]].values )[1] # P 值绝对值越大,显著性差异越大 mat[i][j] = p_val # 热力图 sns.heatmap(mat, xticklabels=key, yticklabels=key) # 过去5年是否有晋升:数据透视表 pivtb = pd.pivot_table( df, values='left', index=['promotion_last_5years', 'salary'], columns=['Work_accident'], aggfunc=np.mean # 聚合函数 ) sns.heatmap(pivtb, vmin=0, vmax=1, cmap=sns.color_palette("Reds", n_colors=256))
分组分析与钻取
向上钻取:汇总分组数据
向下钻取:展开分组,查看数据的细节
Gini系数:有标注的情况下可以使用。
D - 标注,被关注的属性(是否离职)
Ck - 被比较的属性(工资水平)
Gini(D) = 1 - sum( (Ck / D)^2 )
对于连续值,需要 (1) 将 C 切分为两部分,计算Gini系数 (2) 遍历不同的切分位置重复(1),得到最小的Gini系数和切分位置
决策树 CART 算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 离散值 sns.barplot( x='salary', y='left', hue='department', data=df ) # 连续值 sc = df['satisfaction_level'] sns.barplot( list(range(len(sc))), sc.sort_values() )
相关分析
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 # 连续值:相关系数 sns.heatmap(df.corr(), vmin=-1, vmax=1) # 自动过滤离散值 # 离散值:熵,条件熵,互信息(熵增益),熵的增益率 # 熵:定义不确定性。都是一类,那么熵就是零;如果各类都差不多,熵最大。 # 条件熵:在一定条件下的熵。 # 相关性:互信息 / 标准差乘积的二次根 m = pd.Series(['x1', 'x1', 'x2', 'x2', 'x2', 'x2']) n = pd.Series(['y1', 'y1', 'y1', 'y2', 'y2', 'y2']) def getEntropy(s): s = pd.Series(s) p = s.groupby(s).count().values / float(len(s)) # 概率 return -(np.log2(p) * p).sum() getEntropy(m) def getCondEntropy(s1, s2): # 获取 S1 下 S2 的分布 d = {} for i in list(range(len(s1))): d[s1[i]] = d.get(s1[i], []) + [s2[i]] return sum([getEntropy(d[k]) * len(d[k]) / float(len(s1)) for k in d]) getCondEntropy(m, n) # 条件熵,不对称 def getEntropyGain(s1, s2): return getEntropy(s2) - getCondEntropy(s1, s2) getEntropyGain(n, m) # 互信息,对称 def getEntropyGainRatio(s1, s2): return getEntropyGain(s1, s2) / getEntropy(s2) getEntropyGainRatio(m, n) # 熵增益率,不对称 import math def getDiscreteCorr(s1, s2): return getEntropyGain(s1, s2) / math.sqrt(getEntropy(s1) * getEntropy(s2)) getDiscreteCorr(m, n) # 离散值的相关性度量,对称 def getProbSS(s): # 概率平方和 s = pd.Series(s) p = s.groupby(s).count().values / float(len(s)) return sum(p**2) def getGini(s1, s2): d = {} for i in list(range(len(s1))): d[s1[i]] = d.get(s1[i], []) + [s2[i]] return 1 - sum([getProbSS(d[k]) * len(d[k]) / float(len(s1)) for k in d]) getGini(m, n) # 基尼系数,不对称
因子分析(成分分析)
探索性因子分析:降维
验证性因子分析:假设检验,相关分析,回归分析等
1 2 3 4 5 6 7 df = pd.read_csv('.\\data\\HR.csv').dropna() pca = PCA(n_components=7) mat = pca.fit_transform(df.drop( # 去掉离散值 labels=['salary', 'department', 'left'], axis=1 )) pca.explained_variance_ratio_
总结
连续 - 连续 :相关系数,假设检验
连续 - 二值离散 :相关系数,连续二值化(最小Gini切分,最大熵增益切分)
连续 - 非二值离散 :相关系数(定序)
二值离散 - 二值离散 :相关系数,熵相关,F分值
非二值离散 - 非二值离散 :熵相关,Gini,相关系数(定序)
特征工程 数据集越好,质量越高,则模型复杂度越低。数据的好坏决定了模型的好坏。需要善于观察数据,积累经验。
特征使用
特征获取
特征处理
特征监控:针对模型的长期使用
现有特征
探寻新特征
数据样本抽样
异常值处理:丢弃或转换异常值
1 2 3 4 5 6 isnull() dropna(subset=['field']) duplicated(['field']) drop_duplicates(['field'], keep='first') # 重复时要保留的项目 interpolate(mthod="", order="") # 插值,根据相邻的两个值的平均值 # 还可以使用条件筛选的方法
标注:确定含义。
特征预处理
特征选择:剔除与标注不相关和冗余的特征,提高效率,提升准确度
数据规约
过滤思想:考察与标注的关系。
包裹思想:确定一个评价指标,通过每次迭代去掉一部分特征,直到评价指标下降过快为止,找到评价指标最优的子集。RFE算法。
嵌入思想:根据模型结果来判断特征的重要性。一般采用正则化的方法。
数据抽样
特征变换:对数、指数、离散、平滑、归一化、数值化、正规化
对指化:扩大或缩小尺度。Softmax。
离散化、分箱:连续值可能会有噪声,或算法不支持连续数据,或数据非线性,需要离散化。
等频、等深:排序,分组,每组元素个数相同。之后再用标记替代该值。
等距、等宽:利用极差等宽划分数据。
自因变量优化:
归一化:缩放到 (0, 1) 之间
标准化:将数据转化为标准形式,标准不做规定。 Z-Score 转化
数值化:
标签化:每一类给一个数字表示,保留原本的信息。
独热编码,One-Hot 编码:转化为向量,每两类之间的距离相等。
正规化:规范化,一般用在对象上(所有特征),模型的参数上(所有参数的L2范数为1)
特征降维
PCA:无标注参与
LDA:有标注参与:不同标注之间距离尽可能大,同一标注之间距离尽可能小。
特征衍生:现有特征相互组合得到的新特征
特征选择
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 pandas as pd import scipy.stats as ss from sklearn.svm import SVR from sklearn.tree import DecisionTreeRegressor from sklearn.feature_selection import SelectKBest, RFE, SelectFromModel # 过滤,包裹,嵌入 # 数据 df = pd.DataFrame({ 'A': ss.norm.rvs(size=10), 'B': ss.norm.rvs(size=10), 'C': ss.norm.rvs(size=10), 'D': np.random.randint(low=0, high=2, size=10) }) x = df.loc[:, ['A', 'B', 'C']] y = df.loc[:, 'D'] # 过滤 skb = SelectKBest(k=2) # 保留 2 个特征 skb.fit(x, y) # 可以用卡方,互信息,F值等 skb.transform(x) # 包裹 rfe = RFE(estimator=SVR(kernel='linear'), n_features_to_select=2, step=1) # step 每次迭代去掉几个特征 rfe.fit_transform(x, y) # 嵌入 sfm = SelectFromModel(estimator=DecisionTreeRegressor(), threshold=0.2) # threshold 决定了保留几个特征 sfm.fit_transform(x, y)
特征变换
1 2 3 4 5 6 7 8 9 10 11 ll = [6, 8, 10, 15, 16, 24, 25, 40, 67] # 等深分箱 pd.qcut(ll, q=3, low=['low']) # pd.qcut(ll, q=3, labels=['low', 'mid', 'high']) # Categories (3, interval[float64]): [(5.999, 13.333] < (13.333, 24.333] < (24.333, 67.0]] # ['low', 'low', 'low', 'mid', 'mid', 'mid', 'high', 'high', 'high'] # 等宽分箱 pd.cut(ll, bins=3) # Categories (3, interval[float64]): [(5.939, 26.333] < (26.333, 46.667] < (46.667, 67.0]] # ['low', 'low', 'low', 'low', 'low', 'low', 'low', 'mid', 'high']
归一化与标准化
1 2 3 from sklearn.preprocessing import MinMaxScaler, StandardScaler MinMaxScaler().fit_transform(np.array([1, 3, 10, 15, 20]).reshape(-1, 1)) StandardScaler().fit_transform(np.array([1, 1, 1, 1, 0, 0, 0, 0]).reshape(-1, 1))
数值化
1 2 3 4 5 6 7 8 from sklearn.preprocessing import LabelEncoder, OneHotEncoder # 标签编码 LabelEncoder().fit_transform(np.array(['Down', 'Up', 'Up', 'Down']).reshape(-1, 1)) # OneHot 编码 lb_encoder = LabelEncoder() lb_trans_f = lb_encoder.fit_transform(np.array(['Red', 'Blue', 'Yello'])) oht_encoder = OneHotEncoder().fit(lb_trans_f.reshape(-1, 1)) oht_encoder.transform(lb_encoder.transform(np.array(['Yello', 'Yello', 'Blue']).reshape(-1, 1))).toarray()
正规化
1 2 from sklearn.preprocessing import Normalizer Normalizer(norm='L1').fit_transform(np.array([[1, 1, 3, -1, 2]])) # 对行正规化
LDA
1 2 3 4 5 6 7 8 9 from sklearn.discriminant_analysis import LinearDiscriminantAnalysis x = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]]) y = np.array([1, 1, 1, 2, 2, 2]) # 降到一维 LinearDiscriminantAnalysis(n_components=1).fit_transform(x, y) # 也可以坐判别器使用 clf = LinearDiscriminantAnalysis(n_components=1).fit(x, y) clf.predict([0.8, 1])
数据预处理
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 import pandas as pd import numpy as np import matplotlib.pyplot as plt %matplotlib inline # %matplotlib notebook import seaborn as sns import scipy.stats as ss from sklearn.decomposition import PCA from sklearn.svm import SVR from sklearn.tree import DecisionTreeRegressor from sklearn.feature_selection import SelectKBest, RFE, SelectFromModel from sklearn.preprocessing import MinMaxScaler, StandardScaler from sklearn.preprocessing import LabelEncoder, OneHotEncoder from sklearn.preprocessing import Normalizer from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.decompositiion import PCA df = pd.read_csv("./data/HR.csv").dropna() # 1. 清洗数据 可以抽样 df = df.dropna(subset=['satisfaction_level', 'last_evaluation']) df = df[df['satisfaction_level'] <= 1][df['salary'] != 'nme'] # 2. 得到标注 label = df['left'] df = df.drop('left', axis=1) # 3. 特征选择:根据相关性矩阵,清除不相关的属性(可选) # 4. 特征处理 # 连续值 scaler_list = [False, False, False, False, False, False, False] col_list = ['satisfaction_level', 'last_evaluation', 'number_project', 'average_monthly_hours', 'time_spend_company', 'Work_accident', 'promotion_last_5years'] for i, scaler in enumerate(scaler_list): if not scaler: df[col_list[i]] = MinMaxScaler().fit_transform(df[col_list[i]].values.reshape(-1, 1)).reshape(1, -1)[0] else: df[col_list[i]] = StandardScaler().fit_transform(df[col_list[i]].values.reshape(-1, 1)).reshape(1, -1)[0] # 离散值 scaler_list = [True, False] col_list = ['department', 'salary'] salary_map = {'low': 0, 'medium': 1, 'high': 2} for i, scaler in enumerate(scaler_list): if not scaler: if col_list[i] == 'salary': df[col_list[i]] = [salary_map[s] for s in df['salary'].values] else: df[col_list[i]] = LabelEncoder().fit_transform(df[col_list[i]]) df[col_list[i]] = MinMaxScaler().fit_transform(df[col_list[i]].values.reshape(-1, 1)).reshape(1, -1)[0] else: df = pd.get_dummies(df, columns=[col_list[i]]) # One Hot # 降维 lower_d = False lower_d_n = 3 if lower_d: df = PCA(n_components=lower_d_n).fit_transform(df.values)
挖掘建模 数据集
训练集 60%
验证集 20% :多次训练验证得到参数最优的模型
测试集 20% :评价模型的泛化能力
切分数据集
1 2 3 4 5 from sklearn.model_selection import train_test_split fv = df.values lv = label.values xtt, xvalid, ytt, yvalid = train_test_split(fv, lv, test_size=0.2) # 验证集 其他 xtrain, xtest, ytrain, ytest = train_test_split(xtt, ytt, test_size=0.25) # 测试集 训练集
存取模型
1 2 3 from sklearn.externals import joblib joblib.dump(knnc, 'knnc') knnc = joblic.load('knnc')
分类:
KNN:
距离:欧氏距离,曼哈顿距离,闵可夫斯基距离
KD 树:快速寻找最近点。
算法思想:找一个点最近的N个邻居,在N个邻居中和哪类最像就是哪类
朴素贝叶斯:
朴素:特征之间是相互独立的
拉普拉斯平滑:0 和 1 需要被平滑,否则无法比较。(加一或减一)
GaussianNB - 特征符合正态分布 - MultinomialNB - 特征为离散值 - BernoulliNB - 特征为二值化离散值
生成模型:先求出输入与输出的联合概率分布,再求类别归类的概率。朴素贝叶斯
判别模型:直接得到输出时对应的最大分类的概率。
决策树:每次根据信息增益最大的切分
连续值需要切分
规则用尽,特征用完:采用投票方式,多次使用特征
过拟合:剪枝
支持向量机
min L=(w^2)/2 st. y(wx+b) >= 1
如果出现异常点, min(max(L))
扩维:核函数
集成方法:弱可学习分类器集合
强可学习:多项式复杂度,效果明显
弱可学习:多项式复杂度,效果不明显
袋装法(并行):多个模型投票(均值)
随机森林:确定树的数量,每棵树用到的特征数,树的训练集
不需要剪枝防止过拟合
提升法(串行):多个模型串联,所有模型加权求和得到结果
Adaboost:精度高,灵活调控,不用担心过拟合,简化特征工程流程
Logistic 映射
人工神经网络
KNN
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 from sklearn.neighbors import NearestNeighbors, KNeighborsClassifier # NearestNeighbors samples = [[0, 0, 2], [1, 0, 0], [0, 0, 1]] neigh = NearestNeighbors(n_neighbors=2, radius=0.4) # 邻居的数量为 2 neigh.fit(samples) neigh.kneighbors([[0, 0, 1.3]], 2, return_distance=False) # 获得最近2个点的索引 # KNeighborsClassifier x = [[0], [1], [2], [3]] y = [0, 0, 1, 1] neigh = KNeighborsClassifier(n_neighbors=3) neigh.fit(x, y) neigh.predict([[1.1]]) # 本文数据集测试 # 引入评价指标 from sklearn.metrics import accuracy_score, recall_score, f1_score knnc = KNeighborsClassifier(n_neighbors=5) knnc.fit(xtrain, ytrain) ypred = knnc.predict(xvalid) print(f'acc:{accuracy_score(yvalid, ypred)}, rec:{recall_score(yvalid, ypred)}, f1:{f1_score(yvalid, ypred)}')
朴素贝叶斯
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from sklearn.naive_bayes import BernoulliNB # 特征是离散二值化的 from sklearn.naive_bayes import GaussianNB # 特征符合高斯分布 models = [ ('KNN', KNeighborsClassifier(n_neighbors=3)), ('GaussianNB', GaussianNB()), ('BernoulliNB', BernoulliNB()) ] for clname, cl in models: cl.fit(xtrain, ytrain) xy = [(xtrain, ytrain), (xvalid, yvalid), (xtest, ytest)] for i in range(len(xy)): xp = xy[i][0] yp = xy[i][1] ypred = cl.predict(xp) print(f'{clname}, {i}: acc:{accuracy_score(yp, ypred)}, rec:{recall_score(yp, ypred)}, f1:{f1_score(yp, ypred)}')
决策树
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 from sklearn.tree import DecisionTreeClassifier models = [ # 参数:max_depth, min_samples_split ('DecisionTreeGini', DecisionTreeClassifier()), ('DecisionTreeEntropy', DecisionTreeClassifier(criterion="entropy")), ] for clname, cl in models: cl.fit(xtrain, ytrain) xy = [(xtrain, ytrain), (xvalid, yvalid), (xtest, ytest)] for i in range(len(xy)): xp = xy[i][0] yp = xy[i][1] ypred = cl.predict(xp) print(f'{clname}, {i}: acc:{accuracy_score(yp, ypred)}, rec:{recall_score(yp, ypred)}, f1:{f1_score(yp, ypred)}') # 绘制决策树 Graphviz 要安装并添加到环境变量中 import pydotplus from sklearn.externals.six import StringIO from sklearn.tree import export_graphviz dot_data = export_graphviz( cl, out_file=None, feature_names=features.columns.values, class_names=['NotLeft', 'Left'], fill=True, rounded=True, special_characters=True ) graph = pydotplus.graph_from_dot_data(dot_data) graph.write_pdf('dt.pdf')
支持向量机
1 2 3 4 5 6 7 8 9 10 11 12 13 from sklearn.svm import SVC models = [ # C 精度,错分点惩罚度 ("SVC", SVC(C=1)), ] for clname, cl in models: cl.fit(xtrain, ytrain) xy = [(xtrain, ytrain), (xvalid, yvalid), (xtest, ytest)] for i in range(len(xy)): xp = xy[i][0] yp = xy[i][1] ypred = cl.predict(xp) print(f'{clname}, {i}: acc:{accuracy_score(yp, ypred)}, rec:{recall_score(yp, ypred)}, f1:{f1_score(yp, ypred)}')
随机森林与Adaboost
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier from sklearn.svm import SVC models = [ # N_estimators 决策树个数,criterion 使用方法,max_features 特征数 # 最大深度,是否有放回采样 ... ("RandomForest", RandomForestClassifier()), # 级联分类器数量,学习率, ("AdaBoost", AdaBoostClassifier()), ] for clname, cl in models: cl.fit(xtrain, ytrain) xy = [(xtrain, ytrain), (xvalid, yvalid), (xtest, ytest)] for i in range(len(xy)): xp = xy[i][0] yp = xy[i][1] ypred = cl.predict(xp) print(f'{clname}, {i}: acc:{accuracy_score(yp, ypred)}, rec:{recall_score(yp, ypred)}, f1:{f1_score(yp, ypred)}')
回归
线性回归:H(X) = w * X
决策树
支持向量机
集成方法
Logistic 回归:一般用作分类器
人工神经网络
感知器的串并联
输入层:输入范围[0, 1]
输出层:one-hot
激活函数:sigmod relu tanh softplus
反向传播算法
随机梯度下降:容易陷入最优解
问题
易受离群点影像,容易过拟合:需要正则化、dropout
结果要 softmax 转化(结果的和为 1)
回归树与提升树
GBDT 梯度提升决策树:泛化能力强
XgBoost :支持并行计算
线性回归
1 2 3 4 5 6 7 8 9 10 from sklearn.linear_model import LinearRegression, Ridge, Lasso from sklearn.metrics import mean_squared_error features = df[['number_project', 'average_monthly_hours']] label = df['last_evaluation'] regr = Ridge(alpha=0.6) regr = Lasso(alpha=0.002) regr = LinearRegression() regr.fit(features.values, label.values) Y_pred = regr.predict(features.values) print(regr.coef_, mean_squared_error(Y_pred, label.values))
Logistic 回归 线性回归
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from sklearn.linear_model import LogisticRegression from sklearn.metrics import mean_squared_error features = df[['number_project', 'average_monthly_hours']] label = df['last_evaluation'] models = [ # penalty 正则化 C 正则化因子 tol 精度 solver 方法 # 迭代次数 ("LogisticRegression", LogisticRegression()), ] for clname, cl in models: cl.fit(xtrain, ytrain) xy = [(xtrain, ytrain), (xvalid, yvalid), (xtest, ytest)] for i in range(len(xy)): xp = xy[i][0] yp = xy[i][1] ypred = cl.predict(xp) print(f'{clname}, {i}: acc:{accuracy_score(yp, ypred)}, rec:{recall_score(yp, ypred)}, f1:{f1_score(yp, ypred)}')
人工神经网络
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 # PyBrain 反向传播算法包 # Keras from keras.models import Sequential from keras.layers.core import Dense, Activation from keras.optimizers import SGD model = Sequential() # 神经网络序列 model.add(Dense(50, input_dim=len(f_v[0]))) # 加入稠密层(参数:输出维度,输入维度),也可以是卷积层 model.add(Activation('sigmoid')) model.add(Dense(2)) # 此处可省略输入层维度 model.add(Activation('softmax')) sgd = SGD(lr=0.1) model.compile(loss='mean_squared_error', optimizer=sgd) #optimizer='adam' model.fit( xtrain, np.array([[0, 1] if i == 1 else [1, 0] for i in ytrain]), nb_epoch=100, batch_size=8999) xy = [(xtrain, ytrain), (xvalid, yvalid), (xtest, ytest)] for i in range(len(xy)): x = xy[i][0] y = xy[i][1] ypred = model.predict_classes(x) print(f'NN, {i}: acc:{accuracy_score(yp, ypred)}, rec:{recall_score(yp, ypred)}, f1:{f1_score(yp, ypred)}')
回归树与提升树
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from sklearn.ensemble import GradientBoostingClassifier models = [ # penalty 正则化 C 正则化因子 tol 精度 solver 方法 # 迭代次数 ("GBDT", GradientBoostingClassifier(max_depth=6, n_estimators=100)), ] for clname, cl in models: cl.fit(xtrain, ytrain) xy = [(xtrain, ytrain), (xvalid, yvalid), (xtest, ytest)] for i in range(len(xy)): xp = xy[i][0] yp = xy[i][1] ypred = cl.predict(xp) print(f'{clname}, {i}: acc:{accuracy_score(yp, ypred)}, rec:{recall_score(yp, ypred)}, f1:{f1_score(yp, ypred)}')
聚类
Kmeans
初试:随机选取N个中心
中心:取数据的均值
距离:欧氏距离
问题
初始中心影像:多随机选几次
离群点:K-Medoids
K的确定:轮廓系数
DBSCAN
E 邻域
核心对象
直接密度可达
密度可达
密度相连
问题
层次聚类
每次连接距离最近的点
簇间距离:最短距离,最长距离,平均距离,Ward
聚类灵活
计算复杂度高
离群点影像大
图分裂
形成连通图,再逐一分裂
承受系数
分裂阈值
自顶向下的算法
图的建立方式、分裂方式可以非常灵活
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 import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import make_circles, make_blobs, make_moons from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering n_samples = 1000 circles = make_circles(n_samples=n_samples, factor=0.5, noise=0.05) # factor 内外圆间距 moons = make_moons(n_samples=n_samples, noise=0.05) blobs = make_blobs(n_samples=n_samples, randon_state=1, noise=0.05, center_box=(-1, 1), cluster_std=0.1) random_data = np.random.rand(n_samples, 2) colors = 'bgrcmyk' data = [circles, moons, blobs, random_data] models = [ ('None', None), # Kmeans ('Kmeans', KMeans(n_clusters=2)), # DBSCAN ('DBSCAN', DBSCAN(min_samples=3, eps=0.2)), # Agglomerative ('Agglomerative', AgglomerativeClustering(n_clusters=3, linkage='ward')), ] ] f = plt.figure() for inx, clt in enumerate(models): clname, clt = clt for i, dataset in enumerate(data): X, Y = dataset if not clt: clt_res = [0 for item in range(len(X))] else: clt.fit(X) clt_res = clt.labels_.astype(np.int) f.add_subplot(len(models), len(data), inx * len(data) + i + 1) [plt.scatter(X[p, 0], X[p, 1], color=colors[clt_res[p]]) for p in range(len(X))] plt.show()
关联规则:反映一个事物与其他事物之间的关联性和相互依存性
项目:一个物品
事务:一次交易种的一个物品清单
项集:若干个项目的集合(一次事务中的)
频繁项集:包含某些固定项目频繁出现
支持度:项集在总项集中出现的概率
置信度:X
发生的情况下,由(X->Y)
中推出Y
的概率
提升度:(X->Y)
置信度 /
Y
支持度
Apriori算法:求取频繁项集
序列规则
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 from itertools import combinations def comb(lst): ret=[] for i in range(1,len(lst)+1): ret+=list(combinations(lst,i)) return ret class AprLayer(object): d=dict() def __init__(self): self.d=dict() class AprNode(object): def __init__(self,node): self.s=set(node) self.size=len(self.s) self.lnk_nodes=dict() self.num=0 def __hash__(self): return hash("__".join(sorted([str(itm) for itm in list(self.s)]))) def __eq__(self, other): if "__".join(sorted([str(itm) for itm in list(self.s)]))=="__".join(sorted([str(itm) for itm in list(other.s)])): return True return False def isSubnode(self,node): return self.s.issubset(node.s) def incNum(self,num=1): self.num+=num def addLnk(self,node): self.lnk_nodes[node]=node.s class AprBlk(): def __init__(self,data): cnt=0 self.apr_layers = dict() self.data_num=len(data) for datum in data: cnt+=1 datum=comb(datum) nodes=[AprNode(da) for da in datum] for node in nodes: if not node.size in self.apr_layers: self.apr_layers[node.size]=AprLayer() if not node in self.apr_layers[node.size].d: self.apr_layers[node.size].d[node]=node self.apr_layers[node.size].d[node].incNum() for node in nodes: if node.size==1: continue for sn in node.s: sub_n=AprNode(node.s-set([sn])) self.apr_layers[node.size-1].d[sub_n].addLnk(node) def getFreqItems(self,thd=1,hd=1): freq_items=[] for layer in self.apr_layers: for node in self.apr_layers[layer].d: if self.apr_layers[layer].d[node].num<thd: continue freq_items.append((self.apr_layers[layer].d[node].s,self.apr_layers[layer].d[node].num)) freq_items.sort(key=lambda x:x[1],reverse = True) return freq_items[:hd] def getConf(self,low=True, h_thd=10, l_thd=1, hd=1): confidence = [] for layer in self.apr_layers: for node in self.apr_layers[layer].d: if self.apr_layers[layer].d[node].num < h_thd: continue for lnk_node in node.lnk_nodes: if lnk_node.num < l_thd: continue conf = float(lnk_node.num) / float(node.num) confidence.append([node.s, node.num, lnk_node.s, lnk_node.num, conf]) confidence.sort(key=lambda x: x[4]) if low: return confidence[:hd] else: return confidence[-hd::-1] class AssctAnaClass(): def fit(self,data): self.apr_blk=AprBlk(data) return self def get_freq(self,thd=1,hd=1): return self.apr_blk.getFreqItems(thd=thd,hd=hd) def get_conf_high(self,thd,h_thd=10): return self.apr_blk.getConf(low=False, h_thd=h_thd, l_thd=thd) def get_conf_low(self,thd,hd,l_thd=1): return self.apr_blk.getConf(h_thd=thd,l_thd=l_thd,hd=hd) def main(): data=[ ["牛奶","啤酒","尿布"], ["牛奶","啤酒","咖啡","尿布"], ["香肠","牛奶","饼干"], ["尿布","果汁","啤酒"], ["钉子","啤酒"], ["尿布","毛巾","香肠"], ["啤酒","毛巾","尿布","饼干"] ] print("Freq",AssctAnaClass().fit(data).get_freq(thd=3,hd=10)) print("Conf",AssctAnaClass().fit(data).get_conf_high(thd=3,h_thd=3)) if __name__=="__main__": main()
半监督学习
生成模型
判别模型
标签传播算法:与已标注的样本相似度高的标为同一个标签
标签传播算法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import numpy as np from sklearn import datasets iris=datasets.load_iris() labels=np.copy(iris.target) random_unlabeled_points=np.random.rand(len(iris.target)) random_unlabeled_points=random_unlabeled_points<0.7 Y=labels[random_unlabeled_points] labels[random_unlabeled_points]=-1 print("Unlabeled Number:",list(labels).count(-1)) from sklearn.semi_supervised import LabelPropagation label_prop_model=LabelPropagation() label_prop_model.fit(iris.data,labels) Y_pred=label_prop_model.predict(iris.data) Y_pred=Y_pred[random_unlabeled_points] from sklearn.metrics import accuracy_score,recall_score,f1_score print("ACC:",accuracy_score(Y,Y_pred)) print("REC:",recall_score(Y,Y_pred,average="micro")) print("F-Score",f1_score(Y,Y_pred,average="micro"))
模型评估 分类模型:
二分类:比较模型的输出和真实标签
Y_pred:输出为概率值,要经过阈值再二值化,得到正负类
混淆矩阵:TP,FN(漏),FP(错),TN
TP[0, 0], FN[1, 0], FP[0, 1], TN[1, 1]
正对角线表示正确分类的部分
正确率:正对角线 / 所有
召回率:TP / 第一列 - 真实的正类中被认出的正类
F-分数:权衡召回率和准确率
查准率:TP / 第一行 - 认出的正类中真正的正类
错误接受率
错误拒绝率
多分类:
多元混淆矩阵:对角线上是分类正确的类
准确率:与二分类一致
召回率、F-分数:
ROC
横轴:FPR
纵轴:TPR - 召回率
阈值:尽量取图像拐点
AUC
增益图
横轴:测试集的比例
纵轴:正样本比例 / 平均比例
反应分类器的分类效果
KS图
横轴:测试集的比例
纵轴:TPR与FPR
反应分类器的区分度
1 2 3 4 5 6 7 8 9 import matplotlib.pyplot as plt from sklearn.metrics import roc_curve, auc, roc_auc_score f = plt.figure() y_pred, y_test = np.array(Yp[:, 1]).reshape((1, -1)[0]), np.array(Ypt[:, 1]).reshape((1, -1)[0]) f.add_subplot(1, 3, 1) fpr, tpr, threshold = roc_curve(y_test, y_pred) plt.plot(fpr, tpr) print('AUC: ', auc(fpr, tpr)) print('AUC_SCORE: ', roc_auc_score(y_test, y_pred))
回归模型
MAE:残差绝对值的平均值,无法求导
MSE:均方差
RMSE:均方差的二次跟
R2_SCORE 决定系数:SSR / SST,预测值的离散程度与真实值的离散程度
1 print('MSE: ', mean_squared_error(y_test, y_pred))
非监督模型
聚类
RMS
轮廓系数:
簇内平均距离(内聚度),簇间平均距离(分离度)
要求数据是服从正态分布
根据业务制定指标
1 2 from sklearn.metrics import silhouette_score print(silhouette_score(X, clt_res.labels_))
关联模型
常用库 数据收集 Beautiful Soup 是一个HTML和XML解析器,可为被解析的页面创建解析树,从而用于从web页面中提取数据。从网页中提取数据的过程称为网页抓取。
安装方法
1 pip install beautifulsoup4
操作指南
Scrapy 是一个用于大规模网页抓取的框架。
安装方法
操作方法
Selenium 是一个倍受欢迎的自动化浏览器工具。在业界常用于测试,但对于网页抓取也非常方便。
操作方法
数据清零与操作 Pandas 是用Python语言编写的,主要用于数据操作和数据分析。
安装方法
操作方法1
操作方法2
PyOD 用于处理异常值。
安装方法
操作方法
NumPy 可进行高速多维数组运算。
安装方法
Spacy 是一个非常有用且灵活的自然语言处理( NLP )库和框架,用于清理创建模型的文本文档。与类似用途的其他库相比,SpaCy速度更快。
安装方法
1 2 pip install -U spacy python -m spacy download en
操作方法
数据可视化 Matplotlib 是Python中最流行的数据可视化库。
安装方法
操作方法
Seaborn 是另一个基于matplotlib的绘图库。它是一个为绘制有吸引力的图像而提供高级接口的python库。matplotlib能实现功能,Seaborn只是以另一种更吸引人的视觉方式来实现。
安装方法
Bokeh 是一个面向现代网页浏览器的交互式可视化库,为大量数据集提供优美的通用图形结构。
安装方法
操作方法
建模 Scikit-learn 是Python构建模型中的佼佼者。支持在机器学习中执行的不同操作,如分类、回归、聚类和模型选择等。
操作方法
TensorFlow 由谷歌开发,是一个流行的深度学习库,可帮助构建、培训不同模型。是一个开放源码的端到端平台。TensorFlow提供简单的模型构建,强大的机器学习生产,以及强大的实验工具和库。
安装方法
操作方法1 操作方法2
PyTorch 是一个基于Python的科学计算包,是NumPy的替代品,可使用GPU的强大功能。
· 深度学习研究型平台,拥有最大灵活性和最快速度
安装方法
操作方法1 操作方法2
模型解释 Lime 是一种算法(库),可以解释任何分类器或回归量的预测。
安装方法
操作方法
H2O 自动化机器学习的市场领导者。提供简单的数据可视化技术,用于表示高度特征交互和非线性模型行为,通过可视化提供机器学习可解释性(MLI),说明建模结果和模型中特征的影响。
操作方法
语音处理 Librosa 是一个用于音乐和音频分析的Python库。它提供了创建音乐信息检索系统所需的构建块。
安装方法
操作方法
Madmom 是一个用于音频数据分析的很棒的Python库。它是一个用Python编写的音频信号处理库,主要用于音乐信息检索(MIR)任务。
安装方法:依赖Numpy,Scipy,Cython,Mido
测试依赖:PyTest,Fuaudio,PuFftw
操作方法
pyAudioAnalysis 是一个用于音频特征提取、分类和分段的Python库,涵盖广泛的音频分析任务,例如:
对未知声音进行分类
检测音频故障并排除长时间录音中的静音时段
进行监督和非监督的分割
提取音频缩略图等等
安装方法:
1 pip install pyAudioAnalysis
图像处理 OpenCV-Python 是用于图像处理的Python API,结合了OpenCV C ++ API和Python语言的最佳特性。主要用于解决计算机视觉问题。
安装方法:
1 pip install opencv-python
操作方法1 操作方法2
Scikit-image 是另一个用于图像处理的python库,是用于执行多个不同图像处理任务的算法集合。可用于图像分割、几何变换、色彩空间操作、分析、过滤,形态学、特征检测等等。
安装方法:依赖Numpy,Scipy,Joblib
1 pip install -U scikit-learn
Pillow 是从PIL(Python Imaging Library)派生出来的,在一些Linux发行版(如Ubuntu)中被用作原始PIL的替代。
安装方法:
操作方法
数据库 Psycopg 是Python编程语言中最流行的PostgreSQL(高级开源代码关系数据库)适配器。
安装方法:
SQLAlchemy 是最流行的数据库语言。SQLAlchemy是pythonSQL工具包和对象关系映射器,它为应用程序开发人员提供了SQL的全部功能,且极具灵活性。
安装方法:
模型部署 Flask 是一个用Python编写的Web框架,广泛用于部署数据科学模型。
操作方法
其他 下面的网站包含了字符编码,文件处理,图像处理,游戏与多媒体,大数据与科学计算,人工智能与机器学习,系统与命令行,数据库,Web框架,安全,GUI库等相关内容。
其他库参考