0x00 数据集合
气球测试集1.0
黄色,小,成人,用手打,不爆炸
黄色,小,成人,用脚踩,爆炸
黄色,小,小孩,用手打,不爆炸
黄色,小,小孩,用脚踩,不爆炸
黄色,大,成人,用手打,爆炸
黄色,大,成人,用脚踩,爆炸
黄色,大,小孩,用手打,不爆炸
黄色,大,小孩,用脚踩,爆炸
紫色,小,成人,用手打,不爆炸
紫色,小,小孩,用手打,不爆炸
紫色,大,成人,用脚踩,爆炸
紫色,大,小孩,用脚踩,爆炸
数据来源https://github.com/carefree0910/MachineLearning/blob/master/_Data/balloon1.0.txt
蘑菇数据集
蘑菇数据集含义
0x01 笔算机器学习
看到是一些颜色、大小、测试人员、测试动作与结果(是否爆炸)的一些数据。
这个数据集比较特别,每个维度(向量)只有2个特征可取值。
1. 颜色==>黄色/紫色
2. 大小==>大/小
3. 测试人员==>成人/小孩
4. 测试动作==>用手打/用脚踩
5. 结果(标签)==>爆炸/不爆炸
离散朴素贝叶斯算法的过程:
[1]计算先验概率分布:(针对标签)
P(爆炸)=P(不爆炸)=0.5
[2]计算条件概率分布:(针对向量)
也就是我们所说的训练
on_counter
不爆炸 爆炸
紫色 黄色 紫色 黄色
[[1/3, 2/3],[1/3, 2/3]]),
小 大
[5/6, 1/6],[1/6, 5/6]]),
小孩 成人
[2/3, 1/3],[1/3 2/3]]),
手 脚
[5/6, 1/6],[1/6, 5/6]])]
[3]预测,利用MAP估计进行评估
有了条件概率分布,我们就可以开始预测了
比如第一条数据
黄色,小,成人,用手打
我们分别计算爆炸和不爆炸的情况
爆炸的评估:
P(爆炸的评估)=P(黄色|爆炸)P(小|爆炸)P(成人|爆炸)P(用手打|爆炸)P(爆炸)
=2/31/62/31/61/2=0.006172839506172839
P(不爆炸的评估)=P(黄色|不爆炸)P(小|不爆炸)P(成人|不爆炸)P(用手打|不爆炸)P(不爆炸)=2/35/61/35/61/2=0.07716049382716048
评估得到:
P(爆炸的评估)<P(不爆炸的评估)
所以评估为不爆炸,和第一个标签一致。
但是有个怪坑,0*任何数=0。
如果我们数据量过小,比如
多了一个数据:
黑色,大,成人,用脚踩,爆炸
那么P(黑色|不爆炸)=0
导致带有黑色的数据的评估
P(不爆炸的评估)=0(恒等于)
导致带有黑色的数据永远是爆炸的。
为了避免这种怪坑,于是引入了平滑项。
平滑项
我们把数据重新修改一下为
黄色,小,成人,用手打,不爆炸
黄色,小,成人,用脚踩,爆炸
黄色,小,小孩,用手打,不爆炸
黄色,小,小孩,用脚踩,不爆炸
黄色,大,成人,用手打,爆炸
黑色,大,成人,用脚踩,爆炸
黄色,大,小孩,用手打,不爆炸
黄色,大,小孩,用脚踩,爆炸
紫色,小,成人,用手打,不爆炸
紫色,小,小孩,用手打,不爆炸
紫色,大,成人,用脚踩,爆炸
紫色,大,小孩,用脚踩,爆炸
这时候,颜色有K=3个特征值可以取,我们引入一个变量(lb)平滑系数
举个例子:
P(黄色|不爆炸)=(不爆炸并且为黄色个素+lb)/(不爆炸总个数+lbK)
=(4+lb)/(6+lbK)
明显的:
当lb=0时,就是我们上面的结果(极大似然估计),
当lb=1时,我们称之为拉普拉斯平滑
0x02 python 伪代码
按照上面的想法把步骤写一下:
TODO:[1]计算先验概率分布:(针对标签)
TODO:[2]计算条件概率分布:(针对向量)
TODO:[3]预测,利用MAP估计进行评估
我们利用一下python的面向对象的方法。
[0] 数据准备
计算机和人不一样,对文字的理解没有人强,却有极强的数字的运算速度。
所以我们第[0]步,进行数据的准备,把各个向量进行整理,按照可能取到的特征值包装为字典,然后用字典,对文字进行映射。
TODO:[0]数据准备
[0.1] 将输入特征(x)和标签(y)分离
输入特征(x):
['黄色', '小', '成人', '用手打'],
['黄色', '小', '成人', '用脚踩'],
['黄色', '小', '小孩', '用手打'],
['黄色', '小', '小孩', '用脚踩'],
['黄色', '大', '成人', '用手打'],
['黄色', '大', '成人', '用脚踩'],
['黄色', '大', '小孩', '用手打'],
['黄色', '大', '小孩', '用脚踩'],
['紫色', '小', '成人', '用手打'],
['紫色', '小', '小孩', '用手打'],
['紫色', '大', '成人', '用脚踩'],
['紫色', '大', '小孩', '用脚踩']]
标签(y):
['不爆炸', '爆炸', '不爆炸', '不爆炸', '爆炸', '爆炸', '不爆炸', '爆炸', '不爆炸', '不爆炸',
'爆炸', '爆炸']
[0.2] 对每个维度生成字典
输入特征(x)的字典:
feat_dic
{'紫色': 0, '黄色': 1},
{'大': 1, '小': 0},
{'小孩': 0, '成人': 1},
{'用手打': 0, '用脚踩': 1}
标签(y)的字典:
label_dic
{'不爆炸': 0, '爆炸': 1}
[0.3] 为了平滑,我们需要计算K(每个向量的特征值个数)
n_possibilities:
颜色/大小/人员/动作
[2, 2, 2, 2]
[0.4] 按照特征值字典进行映射
(feat_dic)对文本的输入特征值进行映射
x=
[1, 0, 1, 0],
[1, 0, 1, 1],
[1, 0, 0, 0],
[1, 0, 0, 1],
[1, 1, 1, 0],
[1, 1, 1, 1],
[1, 1, 0, 0],
[1, 1, 0, 1],
[0, 0, 1, 0],
[0, 0, 0, 0],
[0, 1, 1, 1],
[0, 1, 0, 1]
label_dic对y进行映射
y
[0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1]
[1] 计算先验概率分布:(针对标签)
[1.0] 统计y中每个特征出现的频率
cat_counter
[6, 6]
[1.1] 计算先验概率分布
p_category
[0.5, 0.5]
[2]计算条件概率分布:(针对向量)
[2.1] 统计每个维度的特征值出现的次数
不爆炸 爆炸
紫色 黄色
颜色[[array([2, 4]), array([2, 4])],
小 大
大小 [array([5, 1]), array([1, 5])],
小孩 成人
人员 [array([4, 2]), array([2, 4])],
手 脚
动作 [array([5, 1]), array([1, 5])]]
[2.2] 利用平滑对数据进行平滑
假设 lb=1 ,拉普拉斯平滑
和n_possibilities [2, 2, 2, 2]
得到data
不爆炸 爆炸
紫色 黄色
[array([[0.375, 0.625],[0.375, 0.625]]),
小 大
array([[0.75, 0.25],[0.25, 0.75]]),
小孩 成人
array([[0.625, 0.375],[0.375, 0.625]]),
手 脚
array([[0.75, 0.25],[0.25, 0.75]])]
到这里训练就已经完成了
[3]预测,利用MAP估计进行评估
到这一步,我们就要开始考虑我们看重哪些数据,或者说如果把训练完后,过了今天要再次预测。我们保存哪些数据可以避免重复训练?
假设我们要训练的样本为
黄色,小,成人,用手打
他的标签为
不爆炸
[3.1] 利用我们之前得到的 feat_dic 对输入特征值进行向量化
feat_dic
{'紫色': 0, '黄色': 1},
{'大': 1, '小': 0},
{'小孩': 0, '成人': 1},
{'用手打': 0, '用脚踩': 1}
得到
[1, 0, 1, 0],
[3.2] 利用data中的数据,和p_categor中的数据
计算
P(0的评估)=0.6250.750.3750.750.5=0.06591796875
P(1的评估)=0.6250.250.6250.250.5=0.01220703125
得到结果为0。
利用一下 label_dic 反字典,得到0表示的是不爆炸。
{'不爆炸': 0, '爆炸': 1}
伪代码就写完了。
可以看出重要的数据都已经列在上面了。接下来是算法的问题。
对于数据,如果有 data(所有的条件概率)、feat_dic (特征值的字典)、和 label_dic(标签的字典) 的反字典就能对数据进行预测。
0X03 python 的面向对象
对于__init__ ,我们希望他有我们上面的这些元素
初始化
class MultinomialNB(NaiveBayes):
def __init__(self):
# 数值化后的输入向量
self._x = None
# 数值化后的标签
self._y = None
# 训练结果,条件概率分布
self._data = None
# 决策函数
self._func = None
# 每个向量的取值情况
self._n_possibilities = None
# 按标签分类后的x
self._labelled_x = None
# 将x,y进行捆绑
self._label_zip = None
# 标签的统计
self._cat_counter = None
# 特征值的统计
self._con_counter = None
# 标签的字典
self.label_dic = None
# 特征值的字典
self._feat_dics = None
然后依次完成以下的任务
TODO:[0]数据准备
TODO:[1]计算先验概率分布:(针对标签)
TODO:[2]计算条件概率分布:(针对向量)
TODO:[3]预测,利用MAP估计进行评估
[0]数据准备
[0.0]数据导入并且[0.1]将输入特征(x)和标签(y)分离
对于数据准备,这个部分很多地方会用到,可以单独扔出来作为一个工具类(Util),也可以当作上面这句话没看见。
import logging
logging.basicConfig(level=logging.DEBUG)
class DataUtil:
/*
* path:文件路径(可以用相对路径)
* train_num:是否设置训练集,训练集的数量
* tar_idx:标签的列号,默认是最后一列
* shuffle:是否对数据集进行洗牌,对于贝叶斯算法,在没有区分训练集的情况下,
* 洗牌只是让最初的数据变得混乱,对最后的结果没有影响
* 这里为了能得到和我们前面的手算结果一致我们就不洗牌了
*/
def get_dataset(path, train_num=None, tar_idx=None, shuffle=False):
x = []
with open(path, "r", encoding="utf-8") as f:
for sample in f:
x.append(sample.strip().split(","))
if shuffle:
np.random.shuffle(x)
# python中的三元运算
tar_idx = -1 if tar_idx is None else tar_idx
y = np.array([xx.pop(tar_idx) for xx in x])
x = np.array(x)
logging.debug("get_dataset-x")
logging.debug(x)
logging.debug("get_dataset-y")
logging.debug(y)
if train_num is None:
return x, y
return (x[:train_num], y[:train_num]), (x[train_num:], y[train_num:])
预处理数据
重新回到我们的 class MultinomialNB(NaiveBayes)
接下来我们要完成:
[0.2] 对每个维度生成字典
[0.3] 为了平滑,我们需要计算K(每个向量的特征值个数)
[0.4] 按照特征值字典进行映射
这些任务
class MultinomialNB(NaiveBayes):
def feed_data(self, x, y, sample_weight=None):
# 进行转置
if isinstance(x, list):
features = map(list, zip(*x))
else:
features = x.T
# 利用集合获取各个维度的特征值
# TODO:[0.2] 对每个维度生成字典
features = [set(feat) for feat in features]
feat_dict = [{_l: i for i, _l in enumerate(feats)} for feats in features]
label_dic = {_l: i for i, _l in enumerate(set(y))}
[0.4] 按照特征值字典进行映射
x = np.array([[feat_dict[i][_l] for i, _l in enumerate(sample)] for sample in x])
y = np.array([label_dic[yy] for yy in y])
[1.0] 统计y中每个特征出现的频率
cat_counter = np.bincount(y)
[0.3] 为了平滑,我们需要计算K(每个向量的特征值个数)
n_possibilities = [len(feads) for feads in features]
# 获取各类别数据的下标
labels = [y == value for value in range(len(cat_counter))]
# 利用下标获取记录按类别分开后的输入数据的数组
labelled_x = [x[ci].T for ci in labels]
self._x = x
logging.debug("self._x")
logging.debug(x)
self._y = y
logging.debug("self._y")
logging.debug(y)
self._labelled_x = labelled_x
logging.debug("labelled_x")
logging.debug(labelled_x)
self._label_zip = list(zip(labels, labelled_x))
logging.debug("_label_zip")
logging.debug(self._label_zip)
self._cat_counter = cat_counter
logging.debug("cat_counter")
logging.debug(cat_counter)
self._feat_dics = feat_dict
logging.debug("feat_dict")
logging.debug(feat_dict)
self._n_possibilities = n_possibilities
logging.debug("n_possibilities")
logging.debug(n_possibilities)
#注意这里是反字典
self.label_dic = {i: _l for _l, i in label_dic.items()}
logging.debug("label_dic")
logging.debug(self.label_dic)
# 处理样本权重的函数,以更新记录概率的数组
self.feed_sample_weight(sample_weight)
logging.debug("feed_sample_weight _con_counter")
logging.debug(self._con_counter)
任务完成了,还顺便把一些比如
[1.0] 统计y中每个特征出现的频率
完成了
留下了一个接口:
self.feed_sample_weight(sample_weight)
用来计算con_counter每个向量特征值的取值情况
也就是[2.1] 统计每个维度的特征值出现的次数
单独扔出来的是为了定制,对不同的权重可以有修改。
[1]计算先验概率分布:(针对标签)
我们的任务是
[1.1] 计算先验概率分布
[1.1] 计算先验概率
# TODO:[1.1] 计算先验概率,lb就是平滑项
# lb为1表示拉普拉斯平滑
def get_prior_probability(self, lb=1):
return [(_c_num + lb) / (len(self._y) + lb * len(self._cat_counter)) \
for _c_num in self._cat_counter]
[2]计算条件概率分布:(针对向量)
也就是我们称为的训练
[2.1] 统计每个维度的特征值出现的次数,使用接口self.feed_sample_weight(sample_weight)
[2.2] 对数据进行平滑
[2.1] 统计每个维度的特征值出现的次数
# TODO:[2.1] 统计每个维度的特征值出现的次数
def feed_sample_weight(self, sample_weight=None):
self._con_counter = []
for dim, _p in enumerate(self._n_possibilities):
if sample_weight is None:
self._con_counter.append([np.bincount(xx[dim], minlength=_p) for xx in self._labelled_x])
else:
self._con_counter.append(
[np.bincount(xx[dim], weights=sample_weight[label] / sample_weight[label].mean(), minlength=_p) for
label, xx in self._label_zip])
[2.2] 对数据进行平滑
def _fit(self, lb):
# 维度
n_dim = len(self._n_possibilities)
# n种结果
n_category = len(self._cat_counter)
# TODO:计算先验概率的函数,lb就是平滑项
p_category = self.get_prior_probability(lb)
logging.debug("p_category")
logging.debug(p_category)
# 初始化 data
# In [1]: [None]*3
# Out[1]: [None, None, None]
data = [None] * n_dim
for dim, n_possibilities in enumerate(self._n_possibilities):
data[dim] = [[(self._con_counter[dim][c][p] + lb) / (self._cat_counter[c] + lb * n_possibilities) \
for p in range(n_possibilities)] for c in range(n_category)]
self._data = [np.array(dim_info) for dim_info in data]
logging.debug("_data")
logging.debug(self._data)
"""
[
array([[0.625, 0.375],
[0.625, 0.375]]),
array([[0.75, 0.25],
[0.25, 0.75]]),
array([[0.375, 0.625],
[0.625, 0.375]]),
array([[0.25, 0.75],
[0.75, 0.25]])]
"""
def func(input_x, tar_category):
rs = 1
for d, xx in enumerate(input_x):
rs *= data[d][tar_category][xx]
return rs * p_category[tar_category]
return func
后面有个小尾巴 def func 是用来返回的,请看下面。
现在我们可以完整的写一下训练的过程了,输入(x,y)的文本,将数据训练好
# TODO:进行训练
def fit(self, x=None, y=None, sample_weight=None, lb=1):
if x is not None and y is not None:
self.feed_data(x, y, sample_weight)
self._func = self._fit(lb)
[3]预测,利用MAP估计进行评估
我们要完成以下任务:
[3.1] 单样本预测
[3.2] 多样本预测
[3.3] 利用数值化后的(x,y)进行评估
[3.1] 单样本预测
# TODO:预测单一样本
def predict_one(self, x, get_raw_result=False):
if isinstance(x, np.ndarray):
x = x.tolist()
else:
x = x[:]
# 相关数值化方法进行数值话
x = self._transfer_x(x)
m_arg = 0
m_probability = 0
for i in range(len(self._cat_counter)):
p = self._func(x, i)
logging.debug("p"+str(i))
logging.debug(p)
if p > m_probability:
m_arg = i
m_probability = p
if not get_raw_result:
return self.label_dic[m_arg]
return m_probability
其中有对标签的数值化函数
self._transfer_x(x)
方法同 feed_data 中的方法
def _transfer_x(self, x):
return x = np.array([feat_dict[i][_l] for i, _l in enumerate(x)])
[3.2] 多样本预测
也就是不停的调用单样本预测
# TODO:多样本预测
def predict(self, x, get_raw_result=False):
return np.array([self.predict_one(xx, get_raw_result) for xx in x])
[3.3] 利用数值化后的(x,y)进行评估
# TODO:对预测进行评估
def evaluate(self, x, y):
y_pred = self.predict(x)
print("正确率:{:12.6}%".format(100 * np.sum(y_pred == y) / len(y)))
[4] 导入和保存数据
到这里就结束了,但是为了更加丰富一下内容。为了能够节约训练的时间(不超过0.001s),或者说就是纯粹为了保存(演示)一下训练结果,和导入训练结果。
[4.1] 保存训练结果
[4.2] 导入训练结果
[4.1] 保存训练结果
def saveresult(self):
np.save(os.path.abspath("./data"), self._data)
print("data保存成功")
np.save(os.path.abspath("./label_dic"), self._laabel_dic)
print("label_dic保存成功")
np.save(os.path.abspath("./feat_dic"), self._feat_dic)
print("_feat_dic保存成功")
[4.2] 导入训练结果
def loadresult(self,datapath,label_dicpath,feat_dic):
self._data = np.load(datapath)
print("datapath导入成功")
print(self._data)
self._label_dic = np.load(label_dicpath)
print("label_dicpath导入成功")
print(self._label_dic)
self._feat_dic= np.load(feat_dic)
print("_feat_dic导入成功")
print(self._feat_dic)
0X04 完整代码
import logging
import numpy as np
logging.basicConfig(level=logging.DEBUG)
class DataUtil:
"""
path: 文件路径(可以用相对路径)
train_num: 是否设置训练集,训练集的数量
tar_idx: 标签的列号,默认是最后一列
shuffle: 是否对数据集进行洗牌,对于贝叶斯算法,在没有区分训练集的情况下,
洗牌只是让最初的数据变得混乱,对最后的结果没有影响
这里为了能得到和我们前面的手算结果一致我们就不洗牌了
"""
def get_dataset(path, train_num=None, tar_idx=None, shuffle=False):
x = []
with open(path, mode="r", encoding="utf-8") as f:
for sample in f:
x.append(sample.strip().split(","))
if shuffle:
np.random.shuffle(x)
# python中的三元运算
tar_idx = -1 if tar_idx is None else tar_idx
y = np.array([xx.pop(tar_idx) for xx in x])
x = np.array(x)
logging.debug("get_dataset-x")
logging.debug(x)
logging.debug("get_dataset-y")
logging.debug(y)
if train_num is None:
return x, y
return (x[:train_num], y[:train_num]), (x[train_num:], y[train_num:])
class MultinomialNB(object):
def __init__(self):
# 数值化后的输入向量
self._x = None
# 数值化后的标签
self._y = None
# 训练结果,条件概率分布
self._data = None
# 决策函数
self._func = None
# 每个向量的取值情况
self._n_possibilities = None
# 按标签分类后的x
self._labelled_x = None
# 将x,y进行捆绑
self._label_zip = None
# 标签的统计
self._cat_counter = None
# 特征值的统计
self._con_counter = None
# 标签的字典
self._label_dic = None
# 特征值的字典
self._feat_dic = None
def feed_data(self, x, y, sample_weight=None):
# 进行转置
if isinstance(x, list):
features = map(list, zip(*x))
else:
features = x.T
# 利用集合获取各个维度的特征值
# TODO:[0.2] 对每个维度生成字典
features = [set(feat) for feat in features]
feat_dict = [{_l: i for i, _l in enumerate(feats)} for feats in features]
label_dic = {_l: i for i, _l in enumerate(set(y))}
# [0.4] 按照特征值字典进行映射
x = np.array([[feat_dict[i][_l] for i, _l in enumerate(sample)] for sample in x])
y = np.array([label_dic[yy] for yy in y])
# [1.0] 统计y中每个特征出现的频率
cat_counter = np.bincount(y)
# [0.3] 为了平滑,我们需要计算K(每个向量的特征值个数)
n_possibilities = [len(feads) for feads in features]
# 获取各类别数据的下标
labels = [y == value for value in range(len(cat_counter))]
# 利用下标获取记录按类别分开后的输入数据的数组
labelled_x = [x[ci].T for ci in labels]
self._x = x
logging.debug("self._x")
logging.debug(x)
self._y = y
logging.debug("self._y")
logging.debug(y)
self._labelled_x = labelled_x
logging.debug("labelled_x")
logging.debug(labelled_x)
self._label_zip = list(zip(labels, labelled_x))
logging.debug("_label_zip")
logging.debug(self._label_zip)
self._cat_counter = cat_counter
logging.debug("cat_counter")
logging.debug(cat_counter)
self._feat_dic = feat_dict
logging.debug("feat_dict")
logging.debug(feat_dict)
self._n_possibilities = n_possibilities
logging.debug("n_possibilities")
logging.debug(n_possibilities)
# 注意这里是反字典
self._label_dic = {i: _l for _l, i in label_dic.items()}
logging.debug("label_dic")
logging.debug(self._label_dic)
# 处理样本权重的函数,以更新记录概率的数组
self.feed_sample_weight(sample_weight)
logging.debug("feed_sample_weight _con_counter")
logging.debug(self._con_counter)
def get_prior_probability(self, lb=1):
return [(_c_num + lb) / (len(self._y) + lb * len(self._cat_counter)) \
for _c_num in self._cat_counter]
def feed_sample_weight(self, sample_weight=None):
self._con_counter = []
for dim, _p in enumerate(self._n_possibilities):
if sample_weight is None:
self._con_counter.append([np.bincount(xx[dim], minlength=_p) for xx in self._labelled_x])
else:
self._con_counter.append(
[np.bincount(xx[dim], weights=sample_weight[label] / sample_weight[label].mean(), minlength=_p) for
label, xx in self._label_zip])
def _fit(self, lb):
# 维度
n_dim = len(self._n_possibilities)
# n种结果
n_category = len(self._cat_counter)
# TODO:计算先验概率的函数,lb就是平滑项
p_category = self.get_prior_probability(lb)
logging.debug("p_category")
logging.debug(p_category)
# 初始化 data
# In [1]: [None]*3
# Out[1]: [None, None, None]
data = [None] * n_dim
for dim, n_possibilities in enumerate(self._n_possibilities):
data[dim] = [[(self._con_counter[dim][c][p] + lb) / (self._cat_counter[c] + lb * n_possibilities) \
for p in range(n_possibilities)] for c in range(n_category)]
self._data = [np.array(dim_info) for dim_info in data]
logging.debug("_data")
logging.debug(self._data)
def func(input_x, tar_category):
rs = 1
for d, xx in enumerate(input_x):
rs *= data[d][tar_category][xx]
return rs * p_category[tar_category]
return func
def fit(self, x=None, y=None, sample_weight=None, lb=1):
if x is not None and y is not None:
self.feed_data(x, y, sample_weight)
self._func = self._fit(lb)
def predict_one(self, x, get_raw_result=False):
if isinstance(x, np.ndarray):
x = x.tolist()
else:
x = x[:]
# 相关数值化方法进行数值话
x = self._transfer_x(x)
m_arg = 0
m_probability = 0
for i in range(len(self._cat_counter)):
p = self._func(x, i)
logging.debug("p" + str(i))
logging.debug(p)
if p > m_probability:
m_arg = i
m_probability = p
if not get_raw_result:
return self._label_dic[m_arg]
return m_probability
def _transfer_x(self, x):
return np.array([self._feat_dic[i][_l] for i, _l in enumerate(x)])
def predict(self, x, get_raw_result=False):
return np.array([self.predict_one(xx, get_raw_result) for xx in x])
def evaluate(self, x, y):
y_pred = self.predict(x)
print("正确率:{:12.6}%".format(100 * np.sum(y_pred == y) / len(y)))
def saveresult(self):
np.save("./data", self._data)
print("data保存成功")
np.save("./label_dic", self._label_dic)
print("label_dic保存成功")
np.save("./feat_dic", self._feat_dic)
print("_feat_dic保存成功")
def loadresult(self, datapath, label_dicpath, feat_dic):
self._data = np.load(datapath)
print("datapath导入成功")
print(self._data)
self._label_dic = np.load(label_dicpath)
print("label_dicpath导入成功")
print(self._label_dic)
self._feat_dic = np.load(feat_dic)
print("_feat_dic导入成功")
print(self._feat_dic)
if __name__ == '__main__':
import time
# TODO:数据导入
# 读入数据
logging.debug("开始导入数据\n")
_x, _y = DataUtil.get_dataset("../balloon1.0.txt")
# 实例化模型并进行训练
# TODO:数据训练
learning_time = time.time()
nb = MultinomialNB()
# nb.loadresult("./data.npy","./label_dic.npy","./feat_dic.npy")
nb.fit(_x, _y)
learning_time = time.time() - learning_time
# TODO:进行评估
estimation_time = time.time()
nb.evaluate(_x, _y)
estimation_time = time.time() - estimation_time
# nb.saveresult()
0X05 后记
如果你看完这篇博客,对其中的一些语句感觉惊讶,“(#`')靠,这都能运行吗?”,可能和我当时看完大佬写的这章的内容有差不多的感受。这篇算是一篇读书笔记吧,半抄半改,默默写注释。
比如这行代码:
def _transfer_x(self, x):
return np.array([self._feat_dic[i][_l] for i, _l in enumerate(x)])
相当与:
x=[]
for j,char in enumerate(x):
x[j]=feat_dict[i][_l] for i,_l in enumerate(x)
x=np.array(x)
return x