xLearn Python API 使用指南¶
xLearn 支持简单易用的 Python 接口。在使用之前,请确保你已经成功安装了 xLearn Python Package. 用户可以进入 Python shell,然后输入如下代码来检查是否成功安装 xLearn Python Package:
>>> import xlearn as xl
>>> xl.hello()
如果你已经成功安装了 xLearn Python Package,你将会看到:
-------------------------------------------------------------------------
_
| |
__ _| | ___ __ _ _ __ _ __
\ \/ / | / _ \/ _` | '__| '_ \
> <| |___| __/ (_| | | | | | |
/_/\_\_____/\___|\__,_|_| |_| |_|
xLearn -- 0.44 Version --
-------------------------------------------------------------------------
快速开始¶
如下代码展示如何使用 xLearn Python API,你可以在 demo/classification/criteo_ctr
路径下找到样例数据 (small_train.txt
and small_test.txt
):
import xlearn as xl
# Training task
ffm_model = xl.create_ffm() # Use field-aware factorization machine (ffm)
ffm_model.setTrain("./small_train.txt") # Set the path of training data
# parameter:
# 0. task: binary classification
# 1. learning rate : 0.2
# 2. regular lambda : 0.002
param = {'task':'binary', 'lr':0.2, 'lambda':0.002}
# Train model
ffm_model.fit(param, "./model.out")
以下是 xLearn 的部分输出:
...
[ ACTION ] Start to train ...
[------------] Epoch Train log_loss Time cost (sec)
[ 10% ] 1 0.595881 0.00
[ 20% ] 2 0.538845 0.00
[ 30% ] 3 0.520051 0.00
[ 40% ] 4 0.504366 0.00
[ 50% ] 5 0.492811 0.00
[ 60% ] 6 0.483286 0.00
[ 70% ] 7 0.472567 0.00
[ 80% ] 8 0.465035 0.00
[ 90% ] 9 0.457047 0.00
[ 100% ] 10 0.448725 0.00
[ ACTION ] Start to save model ...
在上述例子中,xLearn 使用 field-aware factorization machines (ffm) 来解决一个机器学习二分类问题。如果想解决回归 (regression) 问题,用户可以通过将 task
参数设置为 reg
来实现:
param = {'task':'reg', 'lr':0.2, 'lambda':0.002}
我们发现,xLearn 训练过后在当前文件夹下产生了一个叫 model.out
的新文件。这个文件用来存储训练后的模型,我们可以用这个模型在未来进行预测:
ffm_model.setTest("./small_test.txt")
ffm_model.predict("./model.out", "./output.txt")
运行上述命令之后,我们在当前文件夹下得到了一个新的文件 output.txt
,这是我们进行预测任务的输出。我们可以通过如下命令显示这个输出文件的前几行数据:
head -n 5 ./output.txt
-1.58631
-0.393496
-0.638334
-0.38465
-1.15343
这里每一行的分数都对应了测试数据中的一行预测样本。负数代表我们预测该样本为负样本,正数代表正样本 (在这个例子中没有)。在 xLearn 中,用户可以将分数通过 setSigmoid()
API 转换到(0-1)之间:
ffm_model.setSigmoid()
ffm_model.setTest("./small_test.txt")
ffm_model.predict("./model.out", "./output.txt")
结果如下:
head -n 5 ./output.txt
0.174698
0.413642
0.353551
0.414588
0.250373
用户还可以使用 setSign()
API 将预测结果转换成 0 或 1:
ffm_model.setSign()
ffm_model.setTest("./small_test.txt")
ffm_model.predict("./model.out", "./output.txt")
结果如下:
head -n 5 ./output.txt
0
0
0
0
0
模型输出¶
用户还可以通过 setTXTModel()
API 将模型输出成人类可读的 TXT
格式,例如:
ffm_model.setTXTModel("./model.txt")
ffm_model.fit(param, "./model.out")
运行上述命令后,我们发现在当前文件夹下生成了一个新的文件 model.txt
,这个文件存储着 TXT
格式的输出模型:
head -n 5 ./model.txt
-1.041
0.31609
0
0
0
对于线性模型来说,TXT 格式的模型输出将每一个模型参数存储在一行。对于 FM 和 FFM,模型将每一个 latent vector 存储在一行。
Linear:
bias: 0
i_0: 0
i_1: 0
i_2: 0
i_3: 0
FM:
bias: 0
i_0: 0
i_1: 0
i_2: 0
i_3: 0
v_0: 5.61937e-06 0.0212581 0.150338 0.222903
v_1: 0.241989 0.0474224 0.128744 0.0995021
v_2: 0.0657265 0.185878 0.0223869 0.140097
v_3: 0.145557 0.202392 0.14798 0.127928
FFM:
bias: 0
i_0: 0
i_1: 0
i_2: 0
i_3: 0
v_0_0: 5.61937e-06 0.0212581 0.150338 0.222903
v_0_1: 0.241989 0.0474224 0.128744 0.0995021
v_0_2: 0.0657265 0.185878 0.0223869 0.140097
v_0_3: 0.145557 0.202392 0.14798 0.127928
v_1_0: 0.219158 0.248771 0.181553 0.241653
v_1_1: 0.0742756 0.106513 0.224874 0.16325
v_1_2: 0.225384 0.240383 0.0411782 0.214497
v_1_3: 0.226711 0.0735065 0.234061 0.103661
v_2_0: 0.0771142 0.128723 0.0988574 0.197446
v_2_1: 0.172285 0.136068 0.148102 0.0234075
v_2_2: 0.152371 0.108065 0.149887 0.211232
v_2_3: 0.123096 0.193212 0.0179155 0.0479647
v_3_0: 0.055902 0.195092 0.0209918 0.0453358
v_3_1: 0.154174 0.144785 0.184828 0.0785329
v_3_2: 0.109711 0.102996 0.227222 0.248076
v_3_3: 0.144264 0.0409806 0.17463 0.083712
在线学习¶
xLearn 提供在线学习的功能,即 xLearn 可以加载之前预训练过的模型继续学习。用户可以通过 setPreModel()
API 来指定预先训练过的模型文件路径。例如:
import xlearn as xl
ffm_model = xl.create_ffm()
ffm_model.setTrain("./small_train.txt")
ffm_model.setValidate("./small_test.txt")
ffm_model.setPreModel("./pre_model")
param = {'task':'binary', 'lr':0.2, 'lambda':0.002}
ffm_model.fit(param, "./model.out")
注意,xLearn 只能加载二进制预训练模型,不能加载 TXT 格式的文本模型。
选择机器学习算法¶
目前,xLearn 可以支持三种不同的机器学习算法,包括了线性模型 (LR)、factorization machine (FM),以及 field-aware factorization machine (FFM):
import xlearn as xl
ffm_model = xl.create_ffm()
fm_model = xl.create_fm()
lr_model = xl.create_linear()
对于 LR 和 FM 算法而言,我们的输入数据格式必须是 CSV
或者 libsvm
. 对于 FFM 算法而言,我们的输入数据必须是 libffm
格式:
libsvm format:
y index_1:value_1 index_2:value_2 ... index_n:value_n
0 0:0.1 1:0.5 3:0.2 ...
0 0:0.2 2:0.3 5:0.1 ...
1 0:0.2 2:0.3 5:0.1 ...
CSV format:
y value_1 value_2 .. value_n
0 0.1 0.2 0.2 ...
1 0.2 0.3 0.1 ...
0 0.1 0.2 0.4 ...
libffm format:
y field_1:index_1:value_1 field_2:index_2:value_2 ...
0 0:0:0.1 1:1:0.5 2:3:0.2 ...
0 0:0:0.2 1:2:0.3 2:5:0.1 ...
1 0:0:0.2 1:2:0.3 2:5:0.1 ...
xLearn 还可以使用 ,
作为数据的分隔符,例如:
libsvm format:
label,index_1:value_1,index_2:value_2 ... index_n:value_n
CSV format:
label,value_1,value_2 .. value_n
libffm format:
label,field_1:index_1:value_1,field_2:index_2:value_2 ...
注意,如果输入的 csv 文件里不含 y
值,用户必须手动向其每一行数据添加一个占位符 (同样针对测试数据)。否则,xLearn 会将第一个元素视为 y
.
LR 和 FM 算法的输入可以是 libffm
格式,xLearn 会忽略其中的 field
项并将其视为 libsvm
格式。
设置 Validation Dataset (验证集)¶
在机器学习中,我们可以通过 Validation Dataset (验证集) 来进行超参数调优。在 xLearn 中,用户可以使用 setValidate()
API 来指定验证集文件,例如:
import xlearn as xl
ffm_model = xl.create_ffm()
ffm_model.setTrain("./small_train.txt")
ffm_model.setValidate("./small_test.txt")
param = {'task':'binary', 'lr':0.2, 'lambda':0.002}
ffm_model.fit(param, "./model.out")
下面是程序的一部分输出:
[ ACTION ] Start to train ...
[------------] Epoch Train log_loss Test log_loss Time cost (sec)
[ 10% ] 1 0.589475 0.535867 0.00
[ 20% ] 2 0.540977 0.546504 0.00
[ 30% ] 3 0.521881 0.531474 0.00
[ 40% ] 4 0.507194 0.530958 0.00
[ 50% ] 5 0.495460 0.530627 0.00
[ 60% ] 6 0.483910 0.533307 0.00
[ 70% ] 7 0.470661 0.527650 0.00
[ 80% ] 8 0.465455 0.532556 0.00
[ 90% ] 9 0.455787 0.538841 0.00
[ ACTION ] Early-stopping at epoch 7
我们可以看到,在这个任务中 Train log_loss
在不断的下降,而 Test log_loss
(validation loss) 则是先下降,后上升。这代表当前我们训练的模型已经 overfit (过拟合)我们的训练数据。
在默认的情况下,xLearn 会在每一轮 epoch 结束后计算 validation loss 的数值,而用户可以使用 metric
参数来制定不同的评价指标。对于分类任务而言,评价指标有:acc
(accuracy), prec
(precision), f1
, 以及 auc
,例如:
param = {'task':'binary', 'lr':0.2, 'lambda':0.002, 'metric': 'acc'}
param = {'task':'binary', 'lr':0.2, 'lambda':0.002, 'metric': 'prec'}
param = {'task':'binary', 'lr':0.2, 'lambda':0.002, 'metric': 'f1'}
param = {'task':'binary', 'lr':0.2, 'lambda':0.002, 'metric': 'auc'}
对于回归任务而言,评价指标包括:mae
, mape
, 以及 rmsd
(或者叫作 rmse
),例如:
param = {'task':'reg', 'lr':0.2, 'lambda':0.002, 'metric': 'rmse'}
param = {'task':'reg', 'lr':0.2, 'lambda':0.002, 'metric': 'mae'}
param = {'task':'reg', 'lr':0.2, 'lambda':0.002, 'metric': 'mape'}
Cross-Validation (交叉验证)¶
在机器学习中,Cross-Validation (交叉验证) 是一种被广泛使用的模型超参数调优技术。在 xLearn 中,用户可以使用 cv()
API 来使用交叉验证功能,例如:
import xlearn as xl
ffm_model = xl.create_ffm()
ffm_model.setTrain("./small_train.txt")
param = {'task':'binary', 'lr':0.2, 'lambda':0.002}
ffm_model.cv(param)
在默认的情况下,xLearn 使用 3-folds 交叉验证 (即将数据集平均分成 3 份),用户也可以通过 fold
参数来指定数据划分的份数,例如:
import xlearn as xl
ffm_model = xl.create_ffm()
ffm_model.setTrain("./small_train.txt")
param = {'task':'binary', 'lr':0.2, 'lambda':0.002, 'fold':5}
ffm_model.cv(param)
上述命令将数据集划分成为 5 份,并且 xLearn 会在最后计算出平均的 validation loss:
[------------] Average log_loss: 0.549758
[ ACTION ] Finish Cross-Validation
[ ACTION ] Clear the xLearn environment ...
[------------] Total time cost: 0.05 (sec)
选择优化算法¶
在 xLearn 中,用户可以通过 opt
参数来选择使用不同的优化算法。目前,xLearn 支持 SGD
, AdaGrad
, 以及 FTRL
这三种优化算法。 在默认的情况下,xLearn 使用 AdaGrad
优化算法:
param = {'task':'binary', 'lr':0.2, 'lambda':0.002, 'opt':'sgd'}
param = {'task':'binary', 'lr':0.2, 'lambda':0.002, 'opt':'adagrad'}
param = {'task':'binary', 'lr':0.2, 'lambda':0.002, 'opt':'ftrl'}
相比于传统的 SGD (随机梯度下降) 算法,AdaGrad 可以自适应的调整学习速率 learning rate,对于不常用的参数进行较大的更新,对于常用的参数进行较小的更新。 正因如此,AdaGrad 算法常用于稀疏数据的优化问题上。除此之外,相比于 AdaGrad,SGD 对学习速率的大小更敏感,这增加了用户调参的难度。
FTRL (Follow-the-Regularized-Leader) 同样被广泛应用于大规模稀疏数据的优化问题上。相比于 SGD 和 AdaGrad, FTRL 需要用户调试更多的超参数,我们将在下一节详细介绍 xLearn 的超参数调优。
超参数调优¶
在机器学习中,hyper-parameter (超参数) 是指在训练之前设置的参数,而模型参数是指在训练过程中更新的参数。超参数调优通常是机器学习训练过程中不可避免的一个环节。
首先,learning rate
(学习速率) 是机器学习中的一个非常重要的超参数,用来控制每次模型迭代时更新的步长。在默认的情况下,这个值在 xLearn 中被设置为 0.2,用户可以通过 lr
参数来改变这个值:
param = {'task':'binary', 'lr':0.2}
param = {'task':'binary', 'lr':0.5}
param = {'task':'binary', 'lr':0.01}
用户还可以通过 -b
选项来控制 regularization (正则项)。xLearn 使用 L2
正则项,这个值被默认设置为 0.00002
:
param = {'task':'binary', 'lr':0.2, 'lambda':0.01}
param = {'task':'binary', 'lr':0.2, 'lambda':0.02}
param = {'task':'binary', 'lr':0.2, 'lambda':0.002}
对于 FTRL 算法来说,除了学习速率和正则项,我们还需要调节其他的超参数,包括:-alpha
, -beta
, -lambda_1
和 -lambda_2
,例如:
param = {'alpha':0.002, 'beta':0.8, 'lambda_1':0.001, 'lambda_2': 1.0}
对于 FM 和 FFM 模型,用户需要通过 -k
选项来设置 latent vector (隐向量) 的长度。在默认的情况下,xLearn 将其设置为 4
:
param = {'task':'binary', 'lr':0.2, 'lambda':0.01, 'k':2}
param = {'task':'binary', 'lr':0.2, 'lambda':0.01, 'k':4}
param = {'task':'binary', 'lr':0.2, 'lambda':0.01, 'k':5}
param = {'task':'binary', 'lr':0.2, 'lambda':0.01, 'k':8}
注意,xLearn 使用了 SSE 硬件指令来加速向量运算,该指令会同时进行向量长度为 4 的运算,因此将 k=2
和 k=4
所需的运算时间是相同的。
除此之外,对于 FM 和 FFM,用户可以通过设置超参数 -u
来调节模型的初始化参数。在默认的情况下,这个值被设置为 0.66
:
param = {'task':'binary', 'lr':0.2, 'lambda':0.01, 'init':0.80}
param = {'task':'binary', 'lr':0.2, 'lambda':0.01, 'init':0.40}
param = {'task':'binary', 'lr':0.2, 'lambda':0.01, 'init':0.10}
迭代次数 & Early-Stop (提前终止)¶
在模型的训练过程中,每一个 epoch 都会遍历整个训练数据。在 xLearn 中,用户可以通过 epoch
参数来设置需要的 epoch 数量:
param = {'task':'binary', 'lr':0.2, 'lambda':0.01, 'epoch':3}
param = {'task':'binary', 'lr':0.2, 'lambda':0.01, 'epoch':5}
param = {'task':'binary', 'lr':0.2, 'lambda':0.01, 'epoch':10}
如果用户设置了 validation dataset (验证集),xLearn 在默认情况下会在得到最好的 validation 结果时进行 early-stop (提前终止训练),例如:
import xlearn as xl
ffm_model = xl.create_ffm()
ffm_model.setTrain("./small_train.txt")
ffm_model.setValidate("./small_test.txt")
param = {'task':'binary', 'lr':0.2, 'lambda':0.002, 'epoch':10}
ffm_model.fit(param, "./model.out")
在上述命令中,我们设置 epoch 的大小为 10,但是 xLearn 会在第 7 轮提前停止训练 (你可能在你的本地计算机上会得到不同的轮次):
Early-stopping at epoch 7
Start to save model ...
用户可以通过 stop_window
参数来设置提前停止机制的窗口大小。即,stop_window=2
意味着如果在后两轮的时间窗口之内都没有比当前更好的验证结果,则停止训练,并保存之前最好的模型:
param = {'task':'binary', 'lr':0.2,
'lambda':0.002, 'epoch':10,
'stop_window':3}
ffm_model.fit(param, "./model.out")
用户可以通过 disableEarlyStop()
API 来禁止 early-stop:
import xlearn as xl
ffm_model = xl.create_ffm()
ffm_model.setTrain("./small_train.txt")
ffm_model.setValidate("./small_test.txt")
ffm_model.disableEarlyStop();
param = {'task':'binary', 'lr':0.2, 'lambda':0.002, 'epoch':10}
ffm_model.fit(param, "./model.out")
在上述命令中,xLearn 将进行完整的 10 轮 epoch 训练。
注意,在默认情况下,如果没有设置 metric,则 xLearn 会通过 test_loss 来选择最佳停止时机。如果设置了 metric,则 xLearn 通过 metric 的值来决定停止时机。
无锁(Lock-free)学习¶
在默认情况下,xLearn 会进行 Hogwild! 无锁学习,该方法通过 CPU 多核进行并行训练,提高 CPU 利用率,加快算法收敛速度。但是,该无锁算法是非确定性的算法 (non-deterministic). 即,如果我们多次运行如下的命令,我们会在每一次运行得到略微不同的 loss 结果:
import xlearn as xl
ffm_model = xl.create_ffm()
ffm_model.setTrain("./small_train.txt")
param = {'task':'binary', 'lr':0.2, 'lambda':0.002}
ffm_model.fit(param, "./model.out")
The 1st time: 0.449056
The 2nd time: 0.449302
The 3nd time: 0.449185
用户可以通过 nthread
参数来设置使用 CPU 核心的数量,例如:
import xlearn as xl
ffm_model = xl.create_ffm()
ffm_model.setTrain("./small_train.txt")
param = {'task':'binary', 'lr':0.2, 'lambda':0.002, 'nthread':4}
ffm_model.fit(param, "./model.out")
上述代码指定使用 4 个 CPU Core 来进行模型训练。如果用户不设置该选项,xLearn 在默认情况下会使用全部的 CPU 核心进行计算。
xLearn 会显示当前使用线程数量的情况:
[------------] xLearn uses 4 threads for training task.
[ ACTION ] Read Problem ...
用户可以通过设置 disableLockFree()
API 禁止多核无锁学习:
import xlearn as xl
ffm_model = xl.create_ffm()
ffm_model.setTrain("./small_train.txt")
ffm_model.disableLockFree()
param = {'task':'binary', 'lr':0.2, 'lambda':0.002}
ffm_model.fit(param, "./model.out")
这时,xLearn 计算的结果是确定性的 (determinnistic):
The 1st time: 0.449172
The 2nd time: 0.449172
The 3nd time: 0.449172
使用 disableLockFree()
的缺点是训练速度会比无锁训练慢很多,我们的建议是在大规模数据训练下开启此功能。
Instance-Wise 归一化¶
对于 FM 和 FFM 来说,xLearn 会默认对特征进行 Instance-Wise Normalizarion (归一化). 在一些大规模稀疏数据的场景 (例如 CTR 预估), 这一技术非常的有效,但是有些时候它也会影响模型的准确率。用户可以通过设置 disableNorm()
API 来关掉该功能:
import xlearn as xl
ffm_model = xl.create_ffm()
ffm_model.setTrain("./small_train.txt")
ffm_model.disableNorm()
param = {'task':'binary', 'lr':0.2, 'lambda':0.002}
ffm_model.fit(param, "./model.out")
注意,如果在训练过程中使用了 Instance-Wise 归一化,用户需要在预测过程中同样使用该功能。
Quiet Model 安静模式¶
xLearn 的训练支持安静模式,在安静模式下,用户通过调用 setQuiet()
API 来使得 xLearn 的训练过程不会计算任何评价指标,这样可以很大程度上提高训练速度:
import xlearn as xl
ffm_model = xl.create_ffm()
ffm_model.setTrain("./small_train.txt")
ffm_model.setQuiet()
param = {'task':'binary', 'lr':0.2, 'lambda':0.002}
ffm_model.fit(param, "./model.out")
DMatrix 转换¶
如下代码展示如何使用 xLearn Python DMatrix API,你可以在 demo/regression/house_price
路径下找到样例数据 (house_price_train.txt
and house_price_test.txt
):
import xlearn as xl
import numpy as np
import pandas as pd
# read file from file
house_price_train = pd.read_csv("house_price_train.txt", header=None, sep="\t")
house_price_test = pd.read_csv("house_price_test.txt", header=None, sep="\t")
# get train X, y
X_train = house_price_train[house_price_train.columns[1:]]
y_train = house_price_train[0]
# get test X, y
X_test = house_price_test[house_price_test.columns[1:]]
y_test = house_price_test[0]
# DMatrix transition, if use field ,use must pass field map(an array) of features
xdm_train = xl.DMatrix(X_train, y_train)
xdm_test = xl.DMatrix(X_test, y_test)
# Training task
fm_model = xl.create_fm() # Use factorization machine
# we use the same API for train from file
# that is, you can also pass xl.DMatrix for this API now
fm_model.setTrain(xdm_train) # Training data
fm_model.setValidate(xdm_test) # Validation data
# param:
# 0. regression task
# 1. learning rate: 0.2
# 2. regular lambda: 0.002
# 3. evaluation metric: mae
param = {'task':'reg', 'lr':0.2,
'lambda':0.002, 'metric':'mae'}
# Start to train
# The trained model will be stored in model.out
fm_model.fit(param, './model_dm.out')
# Prediction task
# we use the same API for test from file
# that is, you can also pass xl.DMatrix for this API now
fm_model.setTest(xdm_test) # Test data
# Start to predict
# The output result will be stored in output.txt
# if no result out path setted, we return res as numpy.ndarray
res = fm_model.predict("./model_dm.out")
注意: 将数据转换成DMatrix进行训练暂时还不支持交叉验证, 我们很快会添加这个特征。
Scikit-learn API¶
xLearn 还可以支持 Scikit-learn API:
import numpy as np
import xlearn as xl
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# Load dataset
iris_data = load_iris()
X = iris_data['data']
y = (iris_data['target'] == 2)
X_train, \
X_val, \
y_train, \
y_val = train_test_split(X, y, test_size=0.3, random_state=0)
# param:
# 0. binary classification
# 1. model scale: 0.1
# 2. epoch number: 10 (auto early-stop)
# 3. learning rate: 0.1
# 4. regular lambda: 1.0
# 5. use sgd optimization method
linear_model = xl.LRModel(task='binary', init=0.1,
epoch=10, lr=0.1,
reg_lambda=1.0, opt='sgd')
# Start to train
linear_model.fit(X_train, y_train,
eval_set=[X_val, y_val],
is_lock_free=False)
# Generate predictions
y_pred = linear_model.predict(X_val)