协同训练二分类

读了很多文章,介绍协同训练时都是说对于某一数据集从不同视图进行协同训练,在学习西瓜书时,书中介绍协同训练并不局限于不同视角,还可以是不同学习器,甚至不同参数,因此本文利用sklearn中的SVM和TREE对相同数据集进行协同训练。
import numpy as np
import pandas as pd
from sklearn import tree
from sklearn import svm
from sklearn import preprocessing

"""对同一组数据集,利用两个分类器进行协同训练"""


class co_train:
    def __init__(self, data, label):
        """
        :param data: 原始数据
        :param label: 标签所在列名
        """
        self.loaddata = data
        self.label = label

    # 数据划分为有标签数据和无标签数据
    def data_load(self):
        label_data = self.loaddata[self.loaddata[self.label].isnull() == False]
        unlabel_data = self.loaddata[self.loaddata[self.label].isnull() == True]
        return label_data, unlabel_data

    # 标签类别转换,若为非数字型,转为数字型
    def label_change(self, label_data, label_name):
        """
        :param label_data: 有标签数据
        :param label_name: 标签数据所在列名
        :return:
        """
        label = label_data[label_name].values

        # 利用OrdinalEncoder进行类别转换
        enc = preprocessing.OrdinalEncoder()
        label_ = enc.fit_transform(label)
        label_data = label_data.drop(label, axis=1)
        label_data[label] = label_
        return label_data

    # 模型训练 SVM,DTtree
    def model_train(self, X, y):
        svmclf = svm.SVC(probability=True)
        treeclf = tree.DecisionTreeClassifier()
        svmclf.fit(X, y)
        treeclf.fit(X, y)
        return svmclf, treeclf

    # 抽取正例评分最高的p个正例和反例评分最高n个反例
    def sample_extract(self, X_data, y_data_pro, y_data, p, n):
        """
        :param X_data: 进行预测的无标签数据集
        :param y_data: 对两类的预测评分集
        :param p: 正例抽取个数
        :param n: 反例抽取个数
        :return:X_res0, y_res0, X_res1, y_res1, X_data
        X_res0: 抽取的正例数据
        y_res0: 正例抽取个数
        X_res1: 抽取的反例数据
        y_res1: 反例抽取个数
        X_data:抽取后的数据,用作下一轮的无标记数据
        """
        y_0 = []
        y_1 = []
        for i in range(len(y_data_pro)):
            y_0.append(y_data_pro[i][0])
            y_1.append(y_data_pro[i][1])
        y_0 = np.array(y_0)
        y_1 = np.array(y_1)
        X_data = pd.DataFrame(X_data)
        X_data['y_0'] = y_0
        X_data['y_1'] = y_1
        X_data['y'] = y_data

        X_data0 = X_data[X_data['y'] == 0.0]
        X_data1 = X_data[X_data['y'] == 1.0]
        # 正例抽取前p行
        if len(X_data0) < p:
            X_res0 = X_data0
            X_data0 = X_data0.drop(X_data0.head(len(X_data0)).index, inplace=False)
        else:
            X_data0.sort_values(by="y_0", inplace=False, ascending=False)
            X_res0 = X_data0.head(p)
            X_data0 = X_data0.drop(X_data0.head(p).index, inplace=False)
        # 反例抽取前n行
        if len(X_data1) < n:
            X_res1 = X_data1
            X_data1 = X_data1.drop(X_data1.head(len(X_data1)).index, inplace=False)
        else:
            X_data1.sort_values(by="y_1", inplace=False, ascending=False)
            X_res1 = X_data1.head(n)
            X_data1 = X_data1.drop(X_data1.head(n).index, inplace=False)
        if X_data0 is None:
            X_data = X_data1
        else:
            X_data = X_data0.append(X_data1)
        # 转换为训练数据
        y_res0 = X_res0['y'].values
        y_res1 = X_res1['y'].values
        X_res0 = X_res0.drop(['y_0', 'y_1', 'y'], axis=1)
        X_res1 = X_res1.drop(['y_0', 'y_1', 'y'], axis=1)
        X_data = X_data.drop(['y_0', 'y_1', 'y'], axis=1)

        return X_res0, y_res0, X_res1, y_res1, X_data

    # dataframe转list
    def df_list(self, data):
        if len(data) != 0:
            data = np.array(data)
            data = list(data)
            for i in range(len(data)):
                if type(data[i]) == float or int:
                    data[i] =data[i]
                else:
                    data[i] = list(data[i])
        else:
            data = []
        return data

    def run(self, p, n):
        label_data, unlabel_data = self.data_load()
        if type(label_data[self.label][0]) is str:
            label_data = self.label_change(label_data, self.label)
        y = label_data[self.label].values
        X = np.array(label_data.drop(self.label, axis=1))
        svm_label_data = X
        tree_label_data = X
        svm_y = y
        tree_y = y
        unlabel_data = unlabel_data.drop(self.label, axis=1)
        unlabel_data = self.df_list(unlabel_data)
        svmclf, treeclf = self.model_train(X, y)
        while len(np.array(unlabel_data)) > 0:

            y_data_pro_svm = svmclf.predict_proba(unlabel_data)
            y_data_svm = svmclf.predict(unlabel_data)
            y_data_pro_tree = treeclf.predict_proba(unlabel_data)
            y_data_tree = treeclf.predict(unlabel_data)
            svm_Xres0, svm_yres0, svm_Xres1, svm_yres1, svmX_data = self.sample_extract(unlabel_data,
                                                                                        y_data_pro_svm, y_data_svm, p,
                                                                                        n)
            tree_Xres0, tree_yres0, tree_Xres1, tree_yres1, treeX_data = self.sample_extract(unlabel_data,
                                                                                             y_data_pro_tree,
                                                                                             y_data_tree, p, n)
            svm_label_data = self.df_list(svm_label_data) + self.df_list(svm_Xres0) + self.df_list(svm_Xres1)
            svm_y = self.df_list(svm_y) + self.df_list(svm_yres0) + self.df_list(svm_yres1)

            tree_label_data = self.df_list(tree_label_data) + self.df_list(tree_Xres0) + self.df_list(tree_Xres1)
            tree_y = self.df_list(tree_y) + self.df_list(tree_yres0) + self.df_list(tree_yres1)
            unlabel_data = self.df_list(svmX_data) + self.df_list(treeX_data)

            unlabel_data = pd.DataFrame(unlabel_data)
            unlabel_data = unlabel_data.drop_duplicates()  # 去重
            unlabel_data = pd.DataFrame(unlabel_data)
            unlabel_data = self.df_list(unlabel_data)
            svmclf = svm.SVC(probability=True)
            treeclf = tree.DecisionTreeClassifier()
            svmclf.fit(svm_label_data, svm_y)
            treeclf.fit(tree_label_data, tree_y)
        return svmclf, treeclf
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SVM-KNN协同训练是一种结合支持向量机和k最近邻分类器分类方法,并且可以使用协同训练来提高模型的性能。以下是一个简单的使用Python和scikit-learn库实现SVM-KNN协同训练的代码示例: ```python from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split from sklearn.svm import SVC from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import accuracy_score # 生成一个二分类问题数据集 X, y = make_classification(n_samples=1000, n_features=10, n_informative=5, n_classes=2, random_state=1) # 将数据集划分为训练集和测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1) # 定义支持向量机模型和k最近邻分类器模型 svm_model = SVC(kernel='linear', probability=True) knn_model = KNeighborsClassifier(n_neighbors=3) # 训练两个模型,并使用测试集进行评估 svm_model.fit(X_train, y_train) knn_model.fit(X_train, y_train) svm_pred = svm_model.predict(X_test) knn_pred = knn_model.predict(X_test) svm_acc = accuracy_score(y_test, svm_pred) knn_acc = accuracy_score(y_test, knn_pred) print("SVM accuracy: {:.2f}%".format(svm_acc * 100)) print("KNN accuracy: {:.2f}%".format(knn_acc * 100)) # 使用协同训练提高模型性能 svm_pred_train = svm_model.predict(X_train) knn_pred_train = knn_model.predict(X_train) X_train_new = np.hstack((X_train, svm_pred_train.reshape(-1, 1), knn_pred_train.reshape(-1, 1))) svm_model_new = SVC(kernel='linear', probability=True) knn_model_new = KNeighborsClassifier(n_neighbors=3) svm_model_new.fit(X_train_new, y_train) knn_model_new.fit(X_train_new, y_train) svm_pred_new = svm_model_new.predict(X_test) knn_pred_new = knn_model_new.predict(X_test) svm_acc_new = accuracy_score(y_test, svm_pred_new) knn_acc_new = accuracy_score(y_test, knn_pred_new) print("SVM-KNN accuracy: {:.2f}%".format(svm_acc_new * 100)) print("KNN-SVM accuracy: {:.2f}%".format(knn_acc_new * 100)) ``` 在上面的代码中,我们首先生成了一个二分类问题的数据集,并将其划分为训练集和测试集。然后,我们定义了两个分类器模型:支持向量机和k最近邻分类器,并对它们进行了训练和评估。接下来,我们使用两个模型对训练集进行预测,并将预测结果作为新特征与原特征合并,然后再使用这些新特征训练新的分类器模型。最后,我们使用测试集对新的模型进行评估,并输出结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值