手写SVM实现情感分析报>=和<=不支持0的NotImplementedError错误
「NotImplementedError: >= and <= don't work with 0.」错误排查指引
这个错误是代码里多处语法错误、变量错误、参数传递错误共同导致的,逐点修正即可正常运行:
问题点明细
- 类构造方法语法错误:Python类的构造函数固定为
__init__(方法名前后各2个下划线),你写的init不会在实例化时自动执行,导致学习率、迭代次数、正则化系数这些属性完全没初始化。 - 大量变量名拼写/大小写错误:
fit方法入参写的是小写x,y,方法内部直接调用未定义的大写X取值- 迭代次数属性名是
self.n_iters,循环里写的是self.niters(漏了中间的下划线) - 遍历用的内置函数拼写错误:正确写法是
enumerate,你写的是enumarate predict方法入参是小写x,内部计算点积时调用了未定义的大写X
- 模型训练参数传反、传错:
fit方法的正确入参顺序是(特征矩阵, 标签数组),你写的clf.fit(trainData, train_vectors)把原始带文本的DataFrame当标签传入,这是触发本次报错的直接原因:执行y <= 0判断时,文本/稀疏矩阵对象和0做大小比较,直接抛出你看到的报错。 - 数据格式不兼容:
TfidfVectorizer输出的是scipy稀疏矩阵,手写numpy实现的SVM无法直接处理,需要先转成稠密numpy数组。 - 标签未做数值化:数据集的标签是字符串类型的
pos/neg,需要先转成1/-1的数值格式才能喂给SVM做训练。 - 你定义的
myKernel函数是空实现,属于冗余代码,当前逻辑下不会触发报错但无实际作用。
修正后可运行代码
from sklearn.feature_extraction.text import TfidfVectorizer import time from sklearn.metrics import classification_report import pandas as pd import numpy as np class SVM: def __init__(self, learning_rate = 0.001, lambda_param = 0.01, n_iters = 1000): self.lr = learning_rate self.lambda_param = lambda_param self.n_iters = n_iters self.w = None self.b = None def fit(self, X, y): # 标签转换为1/-1的二分类格式 y_ = np.where(y <= 0, -1, 1) n_samples, n_features = X.shape self.w = np.zeros(n_features) self.b = 0 for _ in range(self.n_iters): for idx, x_i in enumerate(X): condition = y_[idx] * (np.dot(x_i, self.w) - self.b) >= 1 if condition: self.w -= self.lr * (2 * self.lambda_param * self.w) else: self.w -= self.lr * (2 * self.lambda_param * self.w - np.dot(x_i, y_[idx])) self.b -= self.lr * y_[idx] def predict(self, X): linear_output = np.dot(X, self.w) - self.b return np.sign(linear_output) # 加载数据集 trainData = pd.read_csv("https://raw.githubusercontent.com/Vasistareddy/sentiment_analysis/master/data/train.csv") testData = pd.read_csv("https://raw.githubusercontent.com/Vasistareddy/sentiment_analysis/master/data/test.csv") # 生成TF-IDF文本特征 vectorizer = TfidfVectorizer(min_df = 5, max_df = 0.8, sublinear_tf = True, use_idf = True) # 稀疏矩阵转稠密数组适配手写numpy SVM train_vectors = vectorizer.fit_transform(trainData['Content']).toarray() test_vectors = vectorizer.transform(testData['Content']).toarray() # 标签数值化:pos映射为1,neg映射为-1 train_labels = np.where(trainData['Label'] == 'pos', 1, -1) test_labels = np.where(testData['Label'] == 'pos', 1, -1) # 模型训练与预测 clf = SVM() t0 = time.time() clf.fit(train_vectors, train_labels) t1 = time.time() prediction_linear = clf.predict(test_vectors) t2 = time.time() time_linear_train = t1-t0 time_linear_predict = t2-t1 # 输出评估结果 print("Results for SVM(linear kernel)") print("Training time: %fs; Prediction time: %fs" % (time_linear_train, time_linear_predict)) report = classification_report(test_labels, prediction_linear, output_dict=True) print('positive: ', report['1']) print('negative: ', report['-1'])
注:当前实现的是线性核SVM,如果需要实现自定义核函数,需要在SVM类中新增核计算逻辑,替换掉现有代码里的线性点积操作。
内容的提问来源于stack exchange,提问作者Adam Hilmi
相关产品推荐
相关产品推荐

