存档2020年8月3日

scikit-learn机器学习

from sklearn import metrics

评分函数评估模型性能

对分类器评分
1. metrics.accuracy_score(y_true,y_pred) 准确率
1. metrics.precision_score(y_true,y_pred) 精确率
1. metrics.recall_score(y_true,y_pred) 召回率(敏感率)

对回归器评分
1. metrics.mean_squared_error(y_true,y_pred) 均方差
1. metrics.explained_variance_score(y_true,y_pred) 可释方差
1. metrics.r2_score(y_true,y_pred) R方值


k-NN算法

k邻近算法 一个数据点很可能与它邻近的点属于同类

# 1. 生成训练数据
train_data, labels = generate_data(11)
# 分离标签数据
blue = train_data[labels.ravel() == 0]
red = train_data[labels.ravel() == 1]
# 画出所有点
plot_data(blue, red)

# 2. 训练分类器
# 创建分类器
knn = cv2.ml.KNearest_create()
# 传入训练数据 成功返回True
knn.train(train_data, cv2.ml.ROW_SAMPLE, labels)

# 3. 预测新数据点的类别
# 生成新的点
newcomer, _ = generate_data(1)
# 绘制新的点
plt.plot(newcomer[0, 0], newcomer[0, 1], 'go', markersize=14)
plt.show()
# 根据最近邻数据点的标签预测新数据点的标签
ret, results, neighbor, dist = knn.findNearest(newcomer, k=3)
print('Predicted label: \t', results)
print('Neighbor label: \t', neighbor)
print('Distance to Neighbor: ', dist)

回归模型预测连续后果

  1. 线性回归, 通过特征的线性组合描述目标变量 如房价预测
    linreg = linear_model.LinearRegression()
    正侧化-降低过拟合过程,
    L1-Lasso回归 linreg = linear_model.Lasso()
    L2-ridge回归 linreg = linear_model.Ridge() /linear_model.RidgeRegression()
  2. 逻辑回归 用于目标的分类模型,把任意输入的实值x转为0~1区间的一个预测值,比如判定物品的种类
    linreg = cv2.ml.LogisticRegression_create()

特征工程

特征选择,特征提取

  1. 数据预处理
    数据格式化,数据清理,数据采样

    1. 特征标准化
      每个点减去所有数据的平均值再除以方差
      x_scaled = preprocessing.scale(x)
      x_scaled.mean(axis=0) 每行均值近似为0 x_scaled.std(axis=0) 每行方差为1
    2. 特征归一化
      L1范数(曼哈顿距离) l1=preprocessing.normalize(X,norm=’l1′)
      L2范数(欧氏距离) l2=preprocessing.normalize(X,norm=’l2′)
    3. 特征缩放在一定范围,一般0~1内
      min_max_scaler = preprocessing.MinMaxScaler() or MinMaxScaler(feature_range(-10,10))
      X_min_max = min_max_scaler.fit_transform(x)
    4. 特征二值化
      binarizer = preprocessing.Binarizer(threshold=0.5)
    5. 缺失数据处理
      mean将nan值换为指定坐标元素的平均值,默认axis=0
      median将nan值换为指定坐标元素的中值,默认axis=0
      most_frequest将nan值换为指定坐标元素中出现频率最高值,默认axis=0
      imp = preprocessing.Imputer(strategy=’mean’)
      x2= imp.fit_transform(x)
  2. 理解降维
    1. 主要成分分析PCA
      特征向量x和y组合成一个特征矩阵X
      x=np.vstack((x,y)).T
      矩阵X上计算PCA,mu投影前减去的平均值eig协方差矩阵的特征向量
      mu, eig = cv2.PCACompute(X,np.array([]))
      旋转投影数据
      x2=cv2.PACAProject(X,mu,eig)
    2. 独立成分分析ICA
      ica=decomposition.FastICA()
      x2=ica.fit_transform(x)
    3. 非负矩阵分解NMF
      nmf = decomposition.NMF()
      x2=nmf.fit_transform(x)
  3. 类别变量表示 类别特征(离散特征)
    独热编码 form sklearn.feature_extraction import DictVectorizer
    vec = DictVectorizer(aparse=False,dtype=int) or aparse=True稀疏矩阵紧凑表示
    vec.fit_transform(data)
    查看特征的顺序表
    vec.get_feature_names()
    某些算法如决策树,本身可以处理类别特征,不再需要使用独热编码

  4. 文本特征表示

    1. 单词计数 缺点:频繁出现的单词赋予过大权重
      form sklearn.feature_extraction.text import CountVectorizer
      vec = CountVectorizer()
      x = vec.fit_transform(data) 将特征矩X保存为一个稀疏矩阵
      x.toarray() 稀疏矩阵转换为常规数组
      vec.get_feature_names() 查看特征名字
      1.词频-逆文档频率TF-IDF 衡量单词在整个数据中出现的频率计算权重
      form sklearn.feature_extraction.text import TfidfVectorizer
      vec = TfidfVectorizer()
      x = vec.fit_transform(data) 将特征矩X保存为一个稀疏矩阵
      x.toarray() 稀疏矩阵转换为常规数组
  5. 图像表示
    1.使用色彩空间

    1. RGB,openCV中是BGR
      img_rgb=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
    2. HSV / HLS /LAB / YUV
      cv2.COLOR_BGR2HSV …

    2.图像角点检测

    1. Harris角点检测(仅灰度图像) corners=cv2.cornerHarris(img_gray,blockSize,Ksize,k)
    2. Shi-Tomasi角点检测 cv2.goodFeaturesToTrack

    3.尺度不度特征变换SIFT
    sift = cv2.xfeatures2d.SIFT_create()

    1. kp = sift.detect(img_bgr) 关键点
      关键点可视化
      img_kp = np.zeros_like(img_bgr)
      img_kp = cv2.drawkeypoints(img_rgb,kp,img_kp,flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
      plt.show()
      计算关键点的特征值
      kp,des=sift.compute(img_bgr,kp) des的每个关键点有128个特征值
    2. 一步检测关键点并计算出特征描述符
      kp2,des2=sift.detectAndCompute(img_bgr,None)
      可以比较des与des2是否相等 print(np.allclose(des,des2))

    4.加速键状特征SURF
    与SIFT一样使用,且商业使用需要授权,比SIFT能得到更多特征,速度更快
    surf = cv2.xfeatures2d.SURF_create()

    5.cv2.ORB 开源代替SIFT,SURF方案
    使用FAST关键点检测子和BRIEF描述符


决策树

决策树是一个简单有效的监督学习算法
1. 数据预处理
得到训练集和测试集
1. 构建决策树
dtree=cv2.ml.dtree_create()
1. 训练决策树
dtree.train=(X_train,cv2.ml.ROW_SAMPLE,y_train)
1. 预测新数据点标签类别
y_pred=dtree.predict(x_test)
1. 检测算法性能-准确率
metrics.accuracy_score(y_test,dtree.predict(X_test)) 测试样本
metrics.accuracy_score(y_train,dtree.predict(X_train)) 训练数据

  1. 可视化训练决策树
    from sklearn import tree
    构造一个空的决策树
    dtc = tree.DecisionTreeClassifier(class_weigth=None,criterion=’gini’ ,max_depth=None,max_features=None,max_leaf_nodes=None,min_impurity_split=1e-07,min_samples_leaf=1,min_samples_split=2,min_weight_fraction_leaf=0.0,presort=False,random_state=None,splitter=’best’)
    fit训练决策树
    dtc.fit(X_train,y_train)
    DecisionTreeClassifier()
    测试准确率
    dtc.score(X_train,y_train)
    dtc.score(X_test,y_test)
    生成决策树文件.Pdf
    $conda install graphviz
    with open(‘tree.dot’,’w’): f=tree.export_graphviz(clf,out_file=f)
    $dot -Tpng tree.dot -o tree.png
    特征重要性评分
    dtc.feature_importances_
    决策规则
    criterion=’gini’ 基尼不纯度,目标是最小化分类错误的概率
    criterion=’entropy’ 信息增益,计算熵,选最低的,完美为0
    控制树的复杂度,避免过拟合,使用预剪枝和后剪枝
    max_depth控制最大深度
    max_leaf_nodes 最多叶结点数量
    min_samples_split 最小数据点数量持续对决策树进行分割
    更复杂的场景使用随机森林

线性回归不能使用gini,entropy,作为代替mse方差缩减,计算真实值和预测值的均方误差 mae计算真实值和预测值的平均绝对值差


支持向量机 SVM

是一种二分化模型,把无法线性分隔的数据映射到高维空间后再找到分类器最优的线性分类器,是一种基于关键点的分类算法,支持向量是离分类器最近的那些点.机器是指分类器,离分类器最近的点到分类器的距离称为间隔,希望间隔尽可能大,就会更准确,也称最大边缘分类器
1. opencv
生成用于后续训练的空分类器模型
svm = cv2.ml.SVM_create()
训练结果 = svm.train(训练数据,训练数据排列格式,训练数据的标签)
训练数据排列格式 cv2.ml.ROW_SAMPLE 按行 cv2.ml.COL_SAMPLE 按列
(返回值,返回结果) = svm.predict(测试数据)
参数调整:setType()设置类别 setKernel()设置核类型 setC()设置支持向量机的参数C(惩罚系数,对误差的宽容度,默认0)
1. sk-learn库
生成可以控制大小和复杂度的随机数据集
make_classification生成随机的n类分类问题,make_regression随机的回归问题,
X, y = datasets.make_classification(n_samples=100, n_features=2,n_redundant=0, n_classes=2,random_state=7816)
方向梯度直方图HOG,是一个图像的特征描述符,常用于人物人类,基本思想对像的局部形状和外观可以使用边缘方向的分布来表示,特别适合纹理丰富的数据.
hog = cv2.HOGDescriptor(win_size, block_size, block_stride, cell_size, num_bins)
调用hog.compute构建样本
X_pos.append(hog.compute(img, (64, 64)))

  1. LIBSVM

贝叶斯学习

一个事件的发生概率可以基于条件的先验知识进行估计,可以用于数据分类,分类正确概率估计.
判别模型,生成模型

# 使用正态贝叶斯分类器
model_norm = cv2.ml.NormalBayesClassifier_create()
# 训练
model_norm.train(X_train, cv2.ml.ROW_SAMPLE, y_train)
# 预测测试
_, y_pred = model_norm.predict(X_test)
# 预测测试评分
print(metrics.accuracy_score(y_test, y_pred))

# 使用朴素贝叶斯分类器
model_naive = naive_bayes.GaussianNB()
# 训练分类器
model_naive.fit(X_train, y_train)
GaussianNB(priors=None)
# 对分类器打分
print('GaussianNB score:', model_naive.score(X_test, y_test))
# 显示决策边界
plot_decision_boundary(model_norm, X, y)
plt.show()
# 预测测试数据,返回y_proba真正概率
yprob = model_naive.predict_proba(X_test)
print(yprob.round(2))

# 使用完整数据训练,需要更复杂的方法,sklearn中的朴素贝叶斯分类器可以处理稀疏矩阵
model_naive = naive_bayes.MultinomialNB()
model_naive.fit(X_train, y_train)

# 使用n-gram提升结果,考虑单词的顺序,但对于更长的文本无法有效的评估权重
counts = feature_extraction.text.CountVectorizer(ngram_range=(1, 2))
X = counts.fit_transform(data['text'].values)
# 分隔
X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size=0.2, random_state=42)
# 训练数据
model_naive = naive_bayes.MultinomialNB()
model_naive.fit(X_train, y_train)
MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)

# 使用TD-IDF提升结果 词频-逆文档频率
tfidf = feature_extraction.text.TfidfTransformer()
X_new = tfidf.fit_transform(X)
X_train, X_test, y_train, y_test = ms.train_test_split(X_new, y, test_size=0.2, random_state=42)
model_naive = naive_bayes.MultinomialNB()
model_naive.fit(X_train, y_train)

非监督学习

降维,因子分析,聚类分析,评估方式使用手动检查,可以作为预处理或特征提取的步骤.
retval,bestLabels,centers = cv2.kmeans(data,K,bestLables,criteria,attempts,flags)
retval 距离值,返回每个点到相应中心距离的平方和,较高紧凑度表明所有点更靠近它们的聚类中心
bestLabels 各个数据点的最终分类标签(索引)
centers 每个分类的中心点数据
data 待处理的数据集合,np.float32类型,每个特征单独一列中
K 要分出簇的个数,常见2,表示2分类
bestLables 各个数据点的最终分类标签(索引),实际中设为None
criteria 算法迭代的终止条件,达到最大循环数目和指定精度阀值时终止,由3个参数构成type,max_iter,eps
type: cv2.TEEM_CRITERIA_EPS 精度满足 MAX_ITER 迭代次数超过阀值max_iter时停止 _EPS+MAX_ITER两个任意一个满足停止
max_iter 最大迭代次数
eps 精确度的阀值
attempts 使用不用的初始值多次(attempts次)偿试
flags 选择初始中心点的方法,主要有3种cv2.KMEANS_RANDOM_CENTERS 随机 cv2.KMEANS_PP_CENTERS基于中心算法 cv2.KMEANS_USE_INITIAL_LABELS 使用用户输入的数据作为第一次分类的中心点,需要多次偿试时后续使用随机或半随机值作为第一次分类中心点

迭代方法,k均值聚类期望最大化 , 高斯混合模型GMM

局限性
无法保证全局最优解(常常让算法在多个初始状态运行)
必须知道聚类个数(肘部法则,轮廓分析,高斯混合模型GMM使用贝叶斯信息准则获得正确数量,具有噪声的基于密度聚类DBSCAN,邻近传播算法)
决策边界是线性的(sklearn谱聚类SpectralClustering)
处理大数据时非常慢(sklearn谱聚类cluster.MiniBatchKMeans)

应用
压缩色彩空间 虽丢失一些细节,介仍可以清楚被识别,另一个方法使用双边滤波器
进行图像分类
字类识别
组织成层次树(c++API 快速最近邻逼近搜索函数cv::flann:hierarchicalClustering sklern自行实现cluster.AgglomerativeClustering)

# 创建4个不同的聚类,一共300个数据点
X, y_true = make_blobs(n_samples=300, centers=4, cluster_std=1.0, random_state=10)
# 算法迭代的终止条件
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)
# 选择初始中心点的方法
flags = cv2.KMEANS_RANDOM_CENTERS
# 聚类分析 指定聚类4,算法初始随机选择尝试次数10
compactness, labels, centers = cv2.kmeans(X.astype(np.float32), 4, None, criteria, 10, flags)

深度学习

人工神经网络 Google-DeepMind Facebook-DeepFace, Keras
McCulloch-Pitts神经元:本质上是一个线性的二元分类器,一般需要训练数据,代价函数,学习规则
感知器:只有当数据是线性可分,且学习率足够小的情况下,感知学习规则才可以保证收敛于最优解
把感知器应用到线性不可分的数据上时,测试结果失败,不存在一条直线可以完美分割
多层感知器MLP,万能逼近特性,给它足够的神经元和层,基本上可以学习任意的输入-输出函数
梯度下降:陷入局部最小值,解决方法可以添加噪声
使用反向传播训练多层感知器,用于估计神经网络中代价函数梯度, 链式法则

# 创建MLP分类器
mlp = cv2.ml.ANN_MLP_create()
# 第一层两个神经元
n_input = 2
# 单个隐藏层8个神经元
n_hidden = 8
# 最后一层两个神经元
n_output = 2
mlp.setLayerSizes(np.array([n_input, n_hidden, n_output]))

# 定制MLP分类器
# 定义网络中每个神经元的激活函数,可以使用自定或openCV
mlp.setActivationFunction(cv2.ml.ANN_MLP_SIGMOID_SYM, 2.5, 1.0)
# 定义一个合适的训练方法
mlp.setTrainMethod(cv2.ml.ANN_MLP_BACKPROP)
# 设置训练过程的终止条件
term_mode = cv2.TERM_CRITERIA_MAX_ITER + cv2.TERM_CRITERIA_EPS
term_max_iter = 300
term_eps = 0.01
mlp.setTermCriteria((term_mode, term_max_iter, term_eps))

# openCV提供激活函数
# cv2.ml.ANN_MLP_IDENTITY 线性激活函数f(x)=x
# cv2.ml.ANN_MLP_SIGMOID_SYM 对称的sigmoid双曲正切
# cv2.ml.ANN_GAUSSIAN 高斯函数 贝尔曲线

# 训练方法
# cv2.ml.ANN_MLP_BACKPROP 反向传播算法,通过mlp.setBackpropMomentumScale 和 mlp.setBackpropWeightScale设置额外的比例因子
# cv2.ml.ANN_MLP_RPROP Rprop算法 通过mlp.setRpropDW0, mlp.setRpropDWMax, mlp.setRpropDWMin, mlp.setRpropDWMinus,  \
#                              mlp.setRpropDWPlus设置额外的参数

# 训练MLP分类器
mlp.train(X, cv2.ml.ROW_SAMPLE, y)
# 预测目标标签
_, y_hat = mlp.predict(X)
# 测量准确率
print(accuracy_score(y_hat.round(), y))


深度学习,人工神经网络开源学习框架
谷歌 TensorFlow
微软 Cognitive Toolkit CNTK
加州大学伯克利分校 Caffe
蒙特利尔大学 Theano
Torch 基于Lua编程语言
Keras 定位一个接口


不同的算法组合

装袋方法(Bagging)
提升方法(Boosting)
随机森林(Random Forest)
自适应提升(AdaBoost)

合适的模型

选择正确的模型就是在偏差和方差之间找一个平衡

交叉验证
常用k折交叉验证,k是用户指定的数字(一般5或10),数据被分成大小差不多相等的k个部分,叫作折,使用k-1折用于训练,另一折用于测试,过程重复进行k次迭代,每次选择不同的折进行测试.
比把数据集分割为训练集和测试集更加稳定和全面

留一法交叉验证

自举
通过使用替代的方法来抽取样本

评估结果’
T检验 两个数据样本是否来自于相同的平均值或者期望值的潜在分布,返回参数p来接受或者驳回一个虚假设,p在0~1内,p=0.05表示这个虚假设仅在100次中正确5次
配对卡方检验 可以用在对对的数据上,来确定两个样本之间是否有任何差异

数据分类:
训练集: 用于构建模型
验证集: 用于选择模型的参数
测试集: 用于评估最终模型的性能

网格搜索结合交叉验证 GridSearchCV
网格搜索嵌套交叉验证
F值(计算精准率和召回率的调和平均值) 公式 2(精准率X召回率)/(精准率+召回率)
设置作业点 PR曲线工具
回归指标:
1. 均方误差 sklearn.metrics.mean_squared_error
1. 可释方差sklearn.metrics.explained_variance_score
1. R2值 sklearn.metrics.r2_score 大部分应用,使用默认的R2就够了
管道 Pipeline


如何解决问题

  1. 问题分类
    1. 按输入分类: 数据已标记,监督学习,通过环境交互来优化,强化学习,没有被标记,非监督学习
    2. 按输出分类: 输出的是数字,回归问题,输出是一个类,分类问题
  2. 找到可用的算法
    可参见速查表 http://aka.ms/MLCheatSheet
  3. 原型构建(实现所有适用的算法)
    1. 使用最少的特征工程,临时应急地实现多个算法
    2. 理想情况下,可以设置一个机器学习管道,使用一组精心准备的指标评测
    3. 特征工程 很重要
    4. 优化超参数

构建自己的估计器

  1. ClassifierMixin if you are writing a classifier (will provide a basic score method) 写一个分类器时
  2. RegressorMixin if you are writing a regressor (will provide a basic score method) 写一个回归器时
  3. ClusterMixin if you are writing a clustering algorithm (will provide a basic fit_predict method) 写一个聚类算法时
  4. TransformerMixin if you are writing a transformer (will provide a basic fit_predict method) 写一个转换器时

    importing BaseEstimator and ClassifierMixin
    class MyClassifier(BaseEstimator, ClassifierMixin):

常用数据集

  1. scikit-learn 内置数据样集
  2. scikit-learn 外部服务载入 mldata.org 参考http://scikit-learn.org/stable/datasets/index.html
  3. Kaggle http://www.kaggle.com 经常比赛,提供一个特定要优化的指标
  4. OpenML http://www.openml.org
  5. 加州大学欧文分校 http://archive.ics.uci.edu/ml/index.php