【问题标题】:Python milk library: object weights issuePython牛奶库:对象权重问题
【发布时间】:2011-12-04 09:32:46
【问题描述】:

我正在尝试使用决策树的 one_vs_one 组合进行多类分类。问题是,当我将不同的对象权重传递给分类器时,结果保持不变。

我对重量有什么误解,还是它们工作不正确?

感谢您的回复!

这是我的代码:

class AdaLearner(object):
    def __init__(self, in_base_type, in_multi_type):
        self.base_type = in_base_type
        self.multi_type = in_multi_type

    def train(self, in_features, in_labels):
        model = AdaBoost(self.base_type, self.multi_type)
        model.learn(in_features, in_labels)

        return model

class AdaBoost(object):
    CLASSIFIERS_NUM = 100
    def __init__(self, in_base_type, in_multi_type):
        self.base_type = in_base_type
        self.multi_type = in_multi_type
        self.classifiers = []
        self.weights = []

    def learn(self, in_features, in_labels):
        labels_number = len(set(in_labels))
        self.weights = self.get_initial_weights(in_labels)

        for iteration in xrange(AdaBoost.CLASSIFIERS_NUM):
            classifier = self.multi_type(self.base_type())
            self.classifiers.append(classifier.train(in_features,
                                                     in_labels,
                                                     weights=self.weights))
            answers = []
            for obj in in_features:
                answers.append(self.classifiers[-1].apply(obj))
            err = self.compute_weighted_error(in_labels, answers)
            print err
            if abs(err - 0.) < 1e-6:
            break

            alpha = 0.5 * log((1 - err)/err)

            self.update_weights(in_labels, answers, alpha)
            self.normalize_weights()

    def apply(self, in_features):
        answers = {}
        for classifier in self.classifiers:
            answer = classifier.apply(in_features)
            if answer in answers:
                answers[answer] += 1
            else:
                answers[answer] = 1
        ranked_answers = sorted(answers.iteritems(),
                                key=lambda (k,v): (v,k),
                                reverse=True)
        return ranked_answers[0][0]

    def compute_weighted_error(self, in_labels, in_answers):
        error = 0.
        w_sum = sum(self.weights)
        for ind in xrange(len(in_labels)):
            error += (in_answers[ind] != in_labels[ind]) * self.weights[ind] / w_sum
        return error

    def update_weights(self, in_labels, in_answers, in_alpha):
        for ind in xrange(len(in_labels)):
            self.weights[ind] *= exp(in_alpha * (in_answers[ind] != in_labels[ind]))

    def normalize_weights(self):
        w_sum = sum(self.weights)
        for ind in xrange(len(self.weights)):
            self.weights[ind] /= w_sum

    def get_initial_weights(self, in_labels):
        weight = 1 / float(len(in_labels))
        result = []
        for i in xrange(len(in_labels)):
            result.append(weight)
        return result

如您所见,它只是一个简单的 AdaBoost(我用 in_base_type = tree_learner, in_multi_type = one_against_one 对其进行了实例化),无论使用多少个基分类器,它的工作方式都是相同的。它只是充当一个多类决策树。 然后我做了一个hack。我在每次迭代中根据它们的权重选择一个随机的对象样本,并使用没有任何权重的随机对象子集训练分类器。这样就可以正常工作了。

【问题讨论】:

  • 能否包含一些代码来演示更改权重和运行分类?
  • 这里是牛奶的作者:我赞同托马斯的观点。这可能是牛奶中的错误或缺乏对该功能的支持,但我需要查看代码。
  • 您是否考虑过清理一下并将其提交给牛奶?如果您对牛奶许可(BSD 简化版)没问题,我可以做一些清理工作。

标签: python machine-learning classification


【解决方案1】:

默认的树标准,即信息增益,没有考虑权重。如果你知道一个公式可以做到这一点,我会实现它。

同时,使用 neg_z1_loss 会正确执行。顺便说一句,该实现中存在一个小错误,因此您需要使用最新的github master

【讨论】:

    猜你喜欢
    • 2013-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-12
    • 1970-01-01
    • 2020-05-12
    • 1970-01-01
    • 2012-07-27
    相关资源
    最近更新 更多