从零实现GaussianNaiveBayes运行报无predict属性错误求助
代码问题排查与修复
核心错误:类方法缩进错误
Python 以缩进作为代码块的划分依据,你写的_calculate_likelihood、predict两个方法没有缩进进入GaussianNaiveBayes类的作用域,属于全局独立函数,不在类的成员属性范围内,所以实例化后调用predict会抛出属性不存在的报错。同时_classify_sample方法的缩进层级错误,需要和类内其他方法对齐。
修复后的完整分类器代码
import numpy as np class GaussianNaiveBayes: def fit(self, X, y): n_samples, n_features = X.shape self._classes = np.unique(y) n_classes = len(self._classes) self._mean = np.zeros((n_classes, n_features), dtype=np.float64) self._var = np.zeros((n_classes, n_features), dtype=np.float64) self._priors = np.zeros(n_classes, dtype=np.float64) # 计算每个类别的均值、方差和先验概率P(H) for i, c in enumerate(self._classes): X_for_class_c = X[y==c] self._mean[i, :] = X_for_class_c.mean(axis=0) self._var[i, :] = X_for_class_c.var(axis=0) + 1e-9 # 加极小值避免方差为0除以零 self._priors[i] = X_for_class_c.shape[0] / float(n_samples) # 计算给定均值和方差时,数据X的似然度P(E|H)的函数 def _calculate_likelihood(self, class_idx, x): mean = self._mean[class_idx] var = self._var[class_idx] num = np.exp(- (x-mean)**2 / (2 * var)) denom = np.sqrt(2 * np.pi * var) return num / denom # 通过计算类别后验概率P(H|E)完成分类 def predict(self, X): y_pred = [self._classify_sample(x) for x in X] return np.array(y_pred) def _classify_sample(self, x): posteriors = [] # 计算每个类别的后验概率 for i, c in enumerate(self._classes): prior = np.log(self._priors[i]) posterior = np.sum(np.log(self._calculate_likelihood(i, x))) posterior = prior + posterior posteriors.append(posterior) # 返回后验概率最高的类别 return self._classes[np.argmax(posteriors)]
测试代码适配修改
你传入fit的y是二维DataFrame格式,会导致类内索引X时报维度错误,需要将y转为一维数组:
from sklearn import datasets from sklearn.model_selection import train_test_split import pandas as pd iris = datasets.load_iris() X = pd.DataFrame(iris.data, columns = iris.feature_names) y = pd.DataFrame(iris.target, columns = ['Target']) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2,random_state = 42) nb = GaussianNaiveBayes() # 把y转为一维数组传入 nb.fit(X_train.values, y_train.values.ravel()) predictions = nb.predict(X_test.values)
额外优化点
- 在方差计算时加了
1e-9的极小偏移量,避免某类特征取值完全一致时方差为0,导致似然计算出现除以零的报错 - 预测时传入X的values属性,避免pandas DataFrame索引和numpy数组运算的兼容问题
内容的提问来源于stack exchange,提问作者Anirban
相关产品推荐
相关产品推荐

