前面实现的朴素贝叶斯分类器,决策函数是非向量化的:
前面提到过大数据处理,尽量避免个人的遍历等一些函数的操作,要借助numpy的强大功能,如下预测函数是按照我们平常习惯写的,先处理一个数据,处理多个数据,就是重复调用单个处理函数。
# =============================================================================
# 模型的评估和预测
# =============================================================================
# 定义预测单一样本的函数
# 参数get_raw_result为控制函数是输出类别(False)还是输出后验概率(True)
def predict_one(self,x,get_raw_result=False):
# 将输入的数据数值化,如果是numpy数组,转化成python的list
# 这时因为python在数值化这个操作上list比较快
if isinstance(x,np.ndarray):
x = x.tolist()
else:
x = x[:]
# 调用相关方法数值化,该方法具体的模型不同而不同
x = self._transfer_x(x)
# 类别和该类别的后验概率,存的是当前最大的
m_arg,m_probability = 0,0
# 遍历各个类别找到最大的后验概率的类别
for i in range(len(self._cat_counter)):
# 决策函数
p = self._func(x,i)
if p > m_probability:
m_arg,m_probability = i, p
if not get_raw_result:
return self.label_dic[m_arg]
return m_probability
# 预测多个样本,就是重复调用一个样本
def predict(self,x,get_raw_result=False):
return np.array([self.predict_one(xx,get_raw_result) for xx in x])
# =============================================================================
# # 利用self._data生成决策函数
# =============================================================================
def func(input_x,tar_category):
rs =1
# 遍历各个纬度,利用data和条件独立假设计算联合条件概率
# d,xx:feature,featureValue
for d,xx in enumerate(input_x):
rs *= data[d][tar_category][xx]
# 利用先验概率和联合条件概率计算后验概率
return rs*p_category[tar_category]
借助于numpy向量化处理,相当于并行计算,注意mask使用技巧,用途较广:
# =============================================================================
# 前面处理的方式为一个一个处理,现在使用向量化的方式
# =============================================================================
def predict_vector(self,x,get_raw_result=False):
# 将输入的数据数值化,如果是numpy数组,转化成python的list
# 这时因为python在数值化这个操作上list比较快
if isinstance(x,np.ndarray):
x = x.tolist()
else:
x = x[:]
# 调用相关方法数值化,该方法具体的模型不同而不同
x = self._transfer_x(x)
# 类别和该类别的后验概率,存的是当前最大的,现在是向量了,长度为x的长度
m_arg,m_probability = np.zeros(len(x)),np.zeros(len(x))
# 遍历各个类别找到最大的后验概率的类别
for i in range(len(self._cat_counter)):
# 决策函数,这里应该是返回的是向量,len(x)数据的后验概率
p = self._func(x,i)
# 这里类似于前面的labels = [y == value for value in range(len(cat_counter))]
# 把满足条件的矩阵mask出俩了
_mask = p > m_probability
m_arg[_mask],m_probability[_mask] = i, p[_mask]
if not get_raw_result:
return np.array([self.label_dic[arg] for arg in m_arg])
return m_probability
# =============================================================================
# 决策函数向量化处理
# =============================================================================
def func_vector(input_x,tar_category):
# 将输入数据为[N个数据,n个属性],我们需要向量化处理,向量是一行一行处理的
# 我们一次处理N个数据的一个属性,需要转置数据
# 为了操作,先转化为numpy
input_x = np.atleast_2d(input_x).T
# rs就是后验概率,大小应该为数据N,初始值为1
rs =np.ones(input_x.shape[1])
# 遍历各个纬度,利用data和条件独立假设计算联合条件概率
# d,xx:feature,featureValue
for d,xx in enumerate(input_x):
# 这里代码没有改变,但是都是向量的操作,[xx]是不是很奇怪,xx是一个
# 向量,numpy支持对向量的操作
rs *= self._data[d][tar_category][xx]
# 利用先验概率和联合条件概率计算后验概率
return rs*p_category[tar_category]