今天折腾了一天算是将FastXML跑通了。不过在评价阶段,我使用了pyxclib而不是FastXML作者提供的matlab评价过程。
下载FastXML代码(也包含PfastreXML,Parabel, SwiftXML这三个模型的代码)
打开FastXML文件夹,根据sample_run.bat
的内容运行train和predict过程。
train完成之后,会在Sandbox/Results/model
文件夹下生成50个.tree文件,对应Bagging的50颗树模型。
predict完成之后,会在Sandbox/Results/
文件夹下生成一个score_mat.txt
文件,其中第i行存储了第i个测试样本在每一个标签上的得分,标签下标升序排列,有一些标签的评分是没有的,也就是得分为0.
接下来就要根据score_mat.txt
计算评价指标。
作者提供的方法是Matlab代码(用这种方法应该要简单一些,不过我电脑上没有安装matlab)。下面介绍如何用pyxclib
评价。
将评价的代码改为:
from xclib.data import data_utils
import xclib.evaluation.xc_metrics as xc_metrics
# Read ground truth and predictions
true_labels = data_utils.read_sparse_file('Sandbox/Data/EUR-Lex/tst_X_Y.txt')
predicted_labels = data_utils.read_sparse_file('Sandbox/Results/EUR-Lex/score_mat.txt')
# evaluate (See examples/evaluate.py for more details)
acc = xc_metrics.Metrics(true_labels=true_labels)
args = acc.eval(predicted_labels, 5)
print(xc_metrics.format(*args))
运行该代码遇到两个问题:
xclib.utils.sparse._read_file_safe
函数出错(sparse.py的line257):indices = np.frombuffer(ind, np.int64)
indptr = np.frombuffer(indptr, dtype=np.int64) # never empty
出错原因是由于ind和indptr这两个变量在_sparse.pyx文件里面的定义是
indices = array.array("l")
indptr = array.array("l", [0])
参考python官方文档可知typcode=l
意味着数组中的数据是signed long
,其中每个值占用4个字节。但xclib的作者将其看成是8个字节,所以利用frombuffer(., np.int64)
进行读取(是平台问题,开发者也认为这是一个wired issue)。
修改:
indices = np.frombuffer(ind, np.int32).astype(np.int64)
indptr = np.frombuffer(indptr, np.int32).astype(np.int64)
然后重新安装xclib,运行评价代码得到结果:
70.70,64.81,59.28,54.16,49.50
70.70,66.15,62.26,59.12,57.23
其中第一行是 P @ 1 % , … , P @ 5 % P@1\%,\dots,P@5\% P@1%,…,P@5%,第二行是 n D C G @ 1 % , … , n D C G @ 5 % nDCG@1\%,\dots,nDCG@5\% nDCG@1%,…,nDCG@5%。
FastXML的作者提供了EUR-Lex4k
数据,根据该数据我们看一下输入数据的格式。
该数据位于Sandbox/Data/EUR-Lex
文件夹下,
其中:
eurlex_test.txt
和eurlex_train.txt
的数据格式如下
样本数量 特征维度 标签数量
l1 l2 ... li a1:b1 a2:b2 ... aj:bj
...
其中l1-li
为[0, 标签数量]
的整数,表示已标注标签。
a1:b1-aj:bj
为稀疏表示的特征向量,ak
为[0,特征维度]
的整数,对应第ak
个特征,bk
表示在ak
特征上的值,bk
是一个实数。
trn_X_Xf.txt
和tst_X_Xf.txt
分别为训练样本集和测试样本集(无标签)。
trn_X_Y.txt
和tst_X_Y.txt
分别为训练标签集和测试标签集(稀疏表示)。
Y_Yf.txt
似乎是每个标签的500维word2vec
,其中有一些空白行。
inv_prop.txt
是每个标签的propensity的倒数。