SVM: 从头开始生成训练后的模型

如何在训练后生成我的模型?我没有使用sklearn包来进行拟合和预测。我的代码如下所示:

class SVM(object):
    def __init__(self, kernel=polynomial_kernel, C=None):
        self.kernel = kernel
        self.C = C
        if self.C is not None: self.C = float(self.C)

    def fit(self, X, y):
        n_samples, n_features = X.shape
        # 格拉姆矩阵
        K = np.zeros((n_samples, n_samples))
        for i in range(n_samples):
            for j in range(n_samples):
                K[i,j] = self.kernel(X[i], X[j])
        P = cvxopt.matrix(np.outer(y,y) * K)
        q = cvxopt.matrix(np.ones(n_samples) * -1)
        A = cvxopt.matrix(y, (1,n_samples))
        b = cvxopt.matrix(0.0)
        if self.C is None:
            G = cvxopt.matrix(np.diag(np.ones(n_samples) * -1))
            h = cvxopt.matrix(np.zeros(n_samples))
        else:
            tmp1 = np.diag(np.ones(n_samples) * -1)
            tmp2 = np.identity(n_samples)
            G = cvxopt.matrix(np.vstack((tmp1, tmp2)))
            tmp1 = np.zeros(n_samples)
            tmp2 = np.ones(n_samples) * self.C
            h = cvxopt.matrix(np.hstack((tmp1, tmp2)))
        # 解决QP问题
        solution = cvxopt.solvers.qp(P, q, G, h, A, b)
        # 拉格朗日乘数
        a = np.ravel(solution['x'])
        # 支持向量具有非零的拉格朗日乘数
        sv = a > 1e-5
        ind = np.arange(len(a))[sv]
        self.a = a[sv]
        self.sv = X[sv]
        self.sv_y = y[sv]
        print("%d个支持向量出自%d个点" % (len(self.a), n_samples))
        # 截距
        self.b = 0
        for n in range(len(self.a)):
            self.b += self.sv_y[n]
            self.b -= np.sum(self.a * self.sv_y * K[ind[n],sv])
        self.b /= len(self.a)
        # 权重向量
        if self.kernel == linear_kernel:
            self.w = np.zeros(n_features)
            for n in range(len(self.a)):
                self.w += self.a[n] * self.sv_y[n] * self.sv[n]
        else:
            self.w = None

    def project(self, X):
        if self.w is not None:
            return np.dot(X, self.w) + self.b
        else:
            y_predict = np.zeros(len(X))
            for i in range(len(X)):
                s = 0
                for a, sv_y, sv in zip(self.a, self.sv_y, self.sv):
                    s += a * sv_y * self.kernel(X[i], sv)
                y_predict[i] = s
            return y_predict + self.b

    def predict(self, X):
        return np.sign(self.project(X))

我在测试文件中尝试显示我的模型:

self.clf = SVM(C=1000.1)
self.svm_model=self.clf.fit(X, Y)
print(self.svm_model)

输出显示:

None

然后我尝试将模型保存到Pickle中:

    SVM_pkl_filename=QtGui.QFileDialog.getSaveFileName(self,'保存文件')
    print ("SVM分类器 :: ", self.svm_model)
    #SVM_pkl_filename = 'SVM_model.pkl'
    SVM_model_pkl = open(SVM_pkl_filename, 'wb')
    # 使用Pickle保存训练好的SVM分类器
    pickle.dump(self.svm_model, SVM_model_pkl)
    # 关闭Pickle实例
    SVM_model_pkl.close()

当我打开保存的文件时,它显示为空。我将其与另一个使用Sklearn保存的模型文件进行了比较,后者有一些随机内容。

我的模型的目的是使用Pickle进行保存和加载。我使用Pickle训练了4个数据集,每次训练我的数据集时我的模型都会更新。并在测试时加载模型。


回答:

问题出在这一行 – self.svm_model=self.clf.fit(X, Y)

请注意,你试图将fit()函数的输出存储到self.svm_model中,但fit()函数没有返回任何内容。

你必须在fit函数中添加return语句,或者在fit()函数中直接对self.svm_model对象进行赋值操作。

另外,我不清楚你希望svm_model包含什么内容。你是想保存权重,还是希望有一个类似scikit-learn的便捷对象,拥有自己的fit()predict()方法?

假设你只想保存权重,可以在fit()函数末尾添加return self.w语句。

pickle无法工作只是这一问题的后果。一旦你解决了svm_model问题,pickle的问题应该会自动解决。

编辑

你的代码中还有另一个条件 –

else:
        self.w = None

这是另一个可能返回None的原因。没有查看执行过程和数据,很难确定具体原因。

在pickle之前进行检查,你可以做一个简单的空值检查。

if not self.svm_model: # 检查是否为None
    # 在这里进行pickle操作

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注