机器学习

半监督学习

半监督学习,也叫自训练,是指通过小样本训练一个分类器,利用分类器去分类未标注样本,再反过来利用得到的数据继续迭代优化分类器的方法。
通过半监督学习学习得到的分类器可能比只通过小样本训练出来的分类器效果要好,毕竟见多识广跑得快。

半监督学习也很有可能是人脑学习新知识的模式。毕竟我们在学习新知识的时候,不会有成千上万的训练数据,而是通过几个例子就能举一反三。

弱监督学习成立的条件在于相似的样本大概率是同一类的,效果的好坏取决于相似性的判断好不好。模型除了向伪标签类学习以外,也会像临近的真标签学习。

比如一开始只标了一张男人的图片是正样本和一张母狗的图片是负样本,然后来一张公狗的图片,你说应该判断成啥?这其实很难说对吧,只有 2 个样本的那个模型也确实很难判断,不过我相信大部分人都会认为公狗应该判为负样本。
这就基于大多数人认为公狗和母狗更相近。
所以公狗这个样本虽然没有标记,但是可以利用某种相似性判断的方式,判断出和母狗更相似,因此 label 一方面是听从原先那个有监督模型的意见,另一方面还要听从相似性的意见,和母狗使用同样的标签。
比如有监督模型给出的是[0.5,0.5],相似性给出[0.1,0.9],那综合起来可能就是[0.3, 0.7],这样就认为公狗的 label 是[0.3,0.7],即更偏向负样本,但没那么确定。
一般来讲人们会让这个 label 更确定一些,也就是盲目自信一些,比如看到 0.3,0.7 就给它变成 0.1,0.9。
这样对于模型来说,有监督模型不知道是该分人和狗还是该分性别,有了相似性的约束信息之后,就更偏向于人和狗的分类了,因此只凭借较少的标注样本,和一套合理的相似性判断方法,就可以得到更准确的分类模型。

样本了之后半监督可以提升指标,那干嘛不都加上个半监督?

因为有成本啊,你还得考虑怎么算相似,你还得有大量没标注的同分布样本,然后你还得付出对那些没标注样本训练的成本,计算量变大,实现麻烦,有的项目还不一定能找到合适的样本或方法。对于大样本量的有监督算法而言,半监督的收益也不是很大。

比如你已经标了 1 亿条了,你再加上 5 亿未标注的数据可能效果也不会有啥提升,因为哪怕你把这 6 亿都标了指标也差不多,因为已经饱和了。

最后,机器学习是一门实验科学。当然大多数情况下没有绝对的,方法不好也许实际 cover 了多数情况,也会有收益。所以收益多少一般都要试一试,与此相比更多的情况可能是任务比较复杂不太适合这么做,或者没有成本这么做。

参考

  1. 小海星机器学习讲义
  2. https://en.wikipedia.org/wiki/Semi-supervised_learning
  3. https://en.wikipedia.org/wiki/Weak_supervision

Google 关于Machine Leaning 的笔记

前几天看了 Google 的一个关于 Machine Learning 的slides,感觉不错,整理一下学习笔记

ML 的定义

An approach to achieve artificial intelligence through systems that can learn from experience to find patterns in that data

ML teaches a computer to recognise patterns by examples, rather than programming it with specific rules.

一个例子:

feature

一般来说,几个属性就代表了几个维度。

有时候更多的维度,更容易做出分类:参考这里

机器学习的分类

监督学习

数据是标注过的

无监督的学习

从没有标注的数据中学习

强化学习

通过带有激励的试错来学习

例子

线性回归(Linear Regression)

聚类

KNN

神经网络

fully-connected 神经网络

深度神经网络(DNN)

深度的意思就是有很多的层。比如说,对于人脸识别,其中某些层可能会识别出线条,然后有的层会识别出眼睛等等

卷积神经网络(CNN)

CNN 可以用来处理图片数据,以及可以表示为图片的数据。要确定一组数据可不可以表示为图片,可以尝试交换任意两行,或者任意两列,如果交换后对数据没有影响,那么就不可以被认为是图片数据。更多细节参看这个 Video

算法的分类

详细讲解请看这里

Regression

回归首先要有一个评价误差的方法,然后迭代的求出模型。回归是一类从统计中得出的方法,比如上面说到的 线性回归(用最小二乘法),还有逻辑回归等等。

Instance Based

Instance Based 是一个决策方法。通过相似度计算找出最接近的实例。比如KNN

Decision Tree

自定向下,做出决策

Bayesian

clustering

association rules

Artificial Neural Network

模拟人的神经系统,比如感知机

深度学习

其实就是很多层的神经网络,比如CNN

降维 (Dimensionality Reduction)

找到数据的内在属性,然后缩减维度,以便能够使用监督学习方法

还有一个ensemble没看懂

机器学习的输出

连续输出

比如拟合好的线性回归跟定一个数值,可以预测另一个数值

概率预测

分类

比如分辨出小猫小狗,或者是识别数字

sklearn 入门笔记

前一阵看了一个叫做 [莫烦 Python][1] 的教程,还有 [sklearn 的官方教程][2] 初步了解了一下 sklearn 的基本概念,不过教程毕竟有些啰嗦,还是自己记录一下关键要点备忘。

机器学习要解决的问题

什么是机器学习?

sklearn 给了一个定义

In general, a learning problem considers a set of n samples of data and then tries to predict properties of unknown data. If each sample is more than a single number and, for instance, a multi-dimensional entry (aka multivariate data), it is said to have several attributes or features.

翻译过来:

总的来说,“学习问题”通过研究一组 n 个样本的数据来预测未知数据的属性。比如说,如果每个样本都不止包含一个数字,而是多维的向量,那么就称它为有多个 feature 属性。

要解决的问题

机器学习的方法不外乎这几类,现在自己用到的应该是分类比较多。

  1. Classification 分类,也就是离散的
  2. Regression 回归,也就是连续的
  3. Clustering 聚类
  4. Dimensionality reduction 数据降维

要实现上面几个目标,可能需要下面的步骤

  1. Model Selection 模型选择
  2. Preprocessing 数据预处理

要去判定自己的任务需要用哪种方法,优先参考 sklearn 官方推出的 cheatsheet(小抄)

sklearn-leanr cheatsheet

sklearn 的数据库

sklearn 为了方便学习自带了一些数据库,可以说是非常方便了。包括了 iris 花瓣数据库,手写数字数据库等。这些例子可以说相当于编程语言的 hello world 或者是图形学届的 utah teapot 了。

除了真实的数据集,还可以使用datasets.make_*系列函数来直接生成一些数据集用来测试。

>>> from sklearn import datasets
>>> iris = datasets.load_iris()          # iris 花瓣数据库
>>> digits = datasets.load_digits()      # 手写数字数据库
>>> print(digits.data)                   # 数据库的输入
[[  0.   0.   5. ...,   0.   0.   0.]
 [  0.   0.   0. ...,  10.   0.   0.]
 [  0.   0.   0. ...,  16.   9.   0.]
 ...,
 [  0.   0.   1. ...,   6.   0.   0.]
 [  0.   0.   2. ...,  12.   0.   0.]
 [  0.   0.  10. ...,  12.   1.   0.]]
>>> digits.target                        # 数据库的输出
array([0, 1, 2, ..., 8, 9, 8])

其中 data 属性是一个二维数组,格式是(n_samples, n_features).

关于如何载入外部数据库,可以看这里,实际上我也还没看,科科

学习与预测

以识别手写数字为例,我们要做的是根据图像识别出数字是什么来。我们需要 fit (训练)出来一个 estimator,然后用来 predict (预测)未知数据的类型。在 sklearn 中,一个 estimator 就是一个实现了 fitpredict 方法的 object。estimator 常用的属性还有 get_params, score 等。

比如我们使用支持向量机模型:

>>> from sklearn import svm
>>> classifier = svm.SVC(gamma=0.001, C=100.)

>>> classifier.fit(digits.data[:-1], digits.target[:-1])  # 注意第一个参数是数据,第二个参数是结果
SVC(C=100.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape="ovr", degree=3, gamma=0.001, kernel="rbf",
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)

# 现在我们开始预测最后一个数据
>>> classifier.predict(digits.data[-1:])
array([8])  # 得出的结果是 8

实际上的图像是

last digit

刚刚的例子是使用前面的数据做训练,然后识别了最后一个数字,其实我们还可以使用 sklearn 自带的 train_test_split 函数来分割数据

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    iris_X, iris_y, test_size=0.3)

# 注意其中训练数据被 sklearn 打乱了。在机器学习中,数据比较乱是比较好的,算法其实也一样,数组是乱的最好。

完整的例子在这里:http://scikit-learn.org/stable/autoexamples/classification/plotdigits_classification.html

保存模型

训练模型还是很花费时间的,我们不可能每次都去训练一个模型,所以一般都是离线训练好了之后,保存下模型来,然后在线调用。保存模型可是直接使用 Python 内置的 pickle 模块,但是一般模型数据都比较大,pickle 对大文件支持不好,最好采用 sklearn 自带的 joblib.

>>> from sklearn.externals import joblib
>>> joblib.dump(classifier, "filename.pkl") 

>>> clf = joblib.load("filename.pkl") 

很简单吧

其他的一些技巧

一些约定

上面说到 sklearn 约定了 fit 和 predict 方法,还有一些其他的约定

  1. 所有的输入都会被转化为 float64 类型
  2. 一半习惯用 X 表示样本数据,y 表示预测结果

可视化

>>> X, y = datasets.make_regression(n_samples=100, n_features=1, n_targets=1, noise=10)
>>> plt.scatter(X, y)
>>> plt.show()

会有下面的图

参考

  1. https://sklearn.apachecn.org/docs/0.21.3/2.html
  2. https://morvanzhou.github.io/tutorials/machine-learning/sklearn/1-1-why/
  3. http://scikit-learn.org/stable/tutorial/basic/tutorial.html

使用 Simhash 进行流式文本消重

要判断两篇文章是否相同,我们可以使用文章的 md5 来判断。但是,一般情况下,文章可能只是改动了一小部分,在搜索引擎中,这种情况是非常常见的,所以需要一种算法来检测相似的文章(near-duplicate)。Simhash 是一个相似度散列算法,也就是说内容相似的文本会产生近似的哈希值。Google 就使用 simhash 作为网页判重的标准。

Simhash 通常采用 64-bit 的数字来作为一个文章的代表,而当两个文章的哈希值差异小于等于 3 位的时候,也就是汉明距离小于等于 3 的时候。

simhash 计算过程

生成 shingle, n-shingling 就是把一个句子或者文章分成 n 个连续单词的组合,然后去重。

比如: the cat sat on the cat

第一步,分组: the cat, cat sat, sat on, on the, the cat
第二步,去重: the cat, cat sat, sat on, on the

文章相似度的检测主要分为两个部分:

  1. 哈希值的构建,也就是 simhash 的算法
  2. 查询系统,给定一篇文章,我们需要查询与他 hash 值类似的文章。

对于中文的 Simhash 计算,首先需要的是分词。但是,不同的分词软件,甚至不同的版本,可能产生截然不同的词,这也就会导致同一个文本计算出来的 Simhash 都不一样。考虑到算法的稳定性,分词并不是一个很好的方案,还不如直接用 3-gram.

工程实现

整个工程实现需要以下几个步骤:

  1. 文本预处理
  2. 倒排索引建立
  3. 查询索引建立 group
  4. 4.

simhash 的召回和 faiss 的

海量文本聚类

来自参考资料 6

做反欺诈时我们做过每天 kw 量级的帖子准实时聚类,用的是 dbscan+simhash 算法,DBSCAN 算法的显著优点是聚类速度快且能够有效处理噪声点和发现任意形状的空间聚类。simhash 算法能够把帖子用一个 hash 来表示,减少对比复杂度,为了减少对比数据量,我们把 64 位的 simhash 每 16 位分成 4 段,只对比四段中至少一段完全一样的。我们把 dbscan 聚类得到的核心点放在一个单独的核心点表中,把每分钟发布的帖子和核心点做 simhash 对比,如果发现该帖子和某核心点密度可达,则把该帖子加入该核心点的聚类,上线后效果不错,每分钟准实时聚类无延时。

参考

  1. http://matpalm.com/resemblance/jaccard_coeff/
  2. http://blog.csdn.net/c289054531/article/details/8082952
  3. 这篇文章一般,有很多谬误
  4. 唯一一篇讲明白了 LSH 原理的文章,如何从高位到低维映射的同时保留相似性
  5. https://github.com/1e0ng/simhash
  6. https://www.zhihu.com/question/20399584/answer/168309597
  7. https://mattilyra.github.io/2017/05/23/document-deduplication-with-lsh.html