多标签学习综述
有分类(classify)任务和排序(rank)任务
本文讨论multi-label ranking (MLR),使用VFDT实现
算法的基本思想是把多标签学习问题转为标签排序问题,该算法通过“成对比较”来实现标签间的排序。
对q个标签,可以构建q(q-1)/2个标签对,所以可以构建q(q-1)/2个数据集。
博客
一颗决策树(decision tree)包含一个根节点、若干内部节点和若干叶节点。叶节点代表决策结果
Hinge Loss 是机器学习领域中的一种损失函数,可用于“最大间隔(max-margin)”分类,其最著名的应用是作为SVM的目标函数。
#读取参数 filename = 'params.csv',文件内容如下图所示
utils.read_params()
loss = params['loss']
data_source = params['data_source']
num_wls = int(params['num_wls'])
num_covs = int(params['num_covs'])
M = int(params['M'])
gamma = params['gamma']
#data_source: emotions
fp = utils.get_filepath(data_source, 'train')
#open(fp, 'rb') 以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头
data = arff.load(open(fp, 'rb'))
class_index, _, _ = utils.parse_attributes(data)
train_rows = data['data']
# Load the test data
fp = utils.get_filepath(data_source, 'test')
data = arff.load(open(fp, 'rb'))
test_rows = data['data']
其中utils.get_filepath()
#os.path.join() 路径拼接 各组件名首字母不包含’/’,则函数会自动加上
#os.getcwd()返回当前进程的工程目录
#os.listdir() 返回指定的文件夹包含的文件或文件夹的名字的列表。
DATA_DIR = os.path.join(os.getcwd(), 'data')
#返回指定文件夹中文件名带有key的文件路径
def get_filepath(dataname, key):
''' Locate the data file and return the path
Args:
dataname (string): folder name that contains the data
key (string): keyword that is a part of the file
Returns:
(string): the file path
'''
file_dir = os.path.join(DATA_DIR, dataname)
for filename in os.listdir(file_dir):
if key in filename:
return os.path.join(file_dir, filename)
return None
enumerate()
函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标
#计算运行时间
start = time.time()
model = AdaOLMR(data_source, loss=loss,
num_covs=num_covs, gamma=gamma)
model.M = M
model.gen_weaklearners(num_wls,
min_grace=5, max_grace=20,
min_tie=0.01, max_tie=0.9,
min_conf=0.01, max_conf=0.9,
min_weight=3, max_weight=10,
seed=seed)
for i, row in enumerate(train_rows):
X = row[:class_index]
Y = row[class_index:]
pred = model.predict(X)
model.update(Y)
cum_error = 0
for i, row in enumerate(test_rows):
X = row[:class_index]
Y = row[class_index:]
pred = model.predict(X)
model.update(Y)
cum_error += utils.rank_loss(pred, model.Y)
end = time.time()
runtime = round(end - start, 2)
avg_loss = round(cum_error / float(len(test_rows)), 4)
安装
pip install liac-arff
pip install sortedcontainers
run_boosting.py文件开始添加
#!/usr/bin/env python
结果很简单,但过程。。。
报错
import: not authorized `np’ @ error/constitute.c/WriteImage/1028
首先在文件开始添加
#!/usr/bin/env python
然后导入arrf时报错,No module named arrf
输入pip install arff,报错:
Traceback (most recent call last):
File “/usr/bin/pip”, line 11, in
sys.exit(main._main())
AttributeError: ‘module’ object has no attribute ‘_main’
原因是之前将升级python3,pip version 10.0.1,按博客改过一些,现在又降为python2.7,所以改回来后解决,安装arff完成。
接着出错ImportError: No module named sortedcontainers,安装后解决
pip install sortedcontainers
报错
TypeError: ‘generator’ object has no attribute ‘getitem’
class_index, _, _ = utils.parse_attributes(data)
for i, attribute in enumerate(data['attributes']):
,关于迭代器data['attributes']
。print(data)
得到 查到:使用pandas读取arff,但安装pandas一直出错
from scipy.io import arff
import pandas as pd
data = arff.loadarff('yeast-train.arff')
df = pd.DataFrame(data[0])
关于pandas.core.frame.DataFrame类
没用
Scipy has a module that can read .arff file and convert that to numpy
array. From there we can convert it to a data frame.
还有arff.loadarff
把import arff 改成 from scipy.io import arff
data, meta = arff.loadarff(‘emotions-test.arff’)
第72个@attribute开始 是分类结果 所以class_index为72
b = a[i:j] 表示复制a[i]到a[j-1],以生成新的list对象 当i缺省时,默认为0,即 a[:3]相当于 a[0:3]
data, meta = arff.loadarff(filepath)
#type(row)
for row in data:
inst = row[:class_index]
用下面的方法可以获得@attribute 的name和类型
meta_names = meta.names()
meta_type = meta.types()
from scipy.io import arff,用arff.loadarff(filepath)来改文件需要修改的地方太多了,改了两个小时,改不下去了,而且还不知道对不对。。。
系统上已经有pycharm,我居然还一直在用gedit看代码。。。
‘generator’ object is not subscriptable
是生成器类型,不能使用索引,所以需要转换成list之后再使用索引
for i, attribute in enumerate(list(data)[‘attributes’]):
TypeError: expected str, bytes or os.PathLike object, not _io.BufferedReader
arff 9.0
data = arff.load(fp)
for row in data:
print(row) #row.Mean_Acc1298_Mean_Mem40_Centroid 会返回对应值 但好像只使用于numeric类型
看了arff的源码__init__.py,class Reader中__iter__(self):就是这部分可以找到@data开始的部分,所以print(row)打印出来的全是@data部分。
但也没有data['data']
之类的操作,看一下liac-arff的源码是怎样的。
先把arff卸载,pip uninstall arff
。然后pip install liac-arff
换成liac-arff后,没报错了,看来论文作者用的就是liac-arff,原来用pip install arff安装的版本太老了。
两者加载文件的区别是
liac-arff:data = arff.load(open(fp, ‘rb’))
arff: data = arff.load(fp)
成功运行
Attribute-Relation File Format缩写,是weka数据挖掘开源程序使用的一种文件模式
ARFF文件结构:可以分为两个部分:头信息和数据信息。
① 头信息(Head information):包括了对关系的声明和对属性的声明;
@attribute
”开头的语句表示,用来定义属性的名称和数据类型。格式为@attribute② 数据信息(Data information):即数据集中给出的数据,“@data
”标记独占一行,剩下的是各个实例的数据,每个实例占一行。实例的各属性值用逗号“,”隔开,缺失值(missing value)用问号“?”表示,且这个问号不能省略。
下面是Weka给出的例子
@relation weather
@attribute outlook {sunny, overcast, rainy}
@attribute temperature real
@attribute humidity real
@attribute windy {TRUE, FALSE}
@attribute play {yes, no}
@data
sunny,85,85,FALSE,no
sunny,80,90,TRUE,no
overcast,83,86,FALSE,yes
rainy,70,96,FALSE,yes
rainy,68,80,FALSE,yes
rainy,65,70,TRUE,no
overcast,64,65,TRUE,yes
sunny,72,95,FALSE,no
sunny,69,70,FALSE,yes
rainy,75,80,FALSE,yes
sunny,75,70,TRUE,yes
overcast,72,90,TRUE,yes
overcast,81,75,FALSE,yes
rainy,71,91,TRUE,no