今天晚上趁着云计算选修课的时间来更新一波。。。。。。
最近一直没啥时间,在做自然语言处理,HDR相关的一些工作(之后有机会会更新),这次试验有点小小的仓促。唉,不得不说,大三,属实开始忙碌起来了。
这次的内容包含四个基本的分类算法。其中,决策树,knn为调用库函数方法,SVM,bayes为手写代码。本博文重在代码实现,笔者对其思想不做过多描述,建议最好在了解其方法思想进行代码实现时观看。
笔者依旧来给实验报告打个草稿,也给各位看官一些参考。
笔者在整理资料时,在平台上参考了不少资料,在此表示感谢。
笔者代码已经经过验证,思路清晰,结果可靠。
笔者强调一下,解决问题的思想是很重要的,写代码前一定要吃透其思想,这样无论多么复杂的程序最终都能够写出来,其花费的时间也不过是调py语法错误的时间而已。
一.实验内容:
1. 掌握主要分类算法的基本原理与实现。
2. 比较不同分类算法的结果,分析其优缺点
根据美国疾病控制预防中心统计,现在美国1/7的成年人患有糖尿病。到2050年,这个比例将会增长至1/3。据分析,是否糖尿病患者与怀孕次数,血糖、血压、皮脂厚度、胰岛素、BMI身体质量指数、糖尿病遗传函数、年龄等特征密切相关。通过机器学习预测是否患有糖尿病,具有非常大的应用价值。
现有一份糖尿病患者数据集diabetes.csv,该数据集有768个数据样本,每个样本有8个特征和一个类别标签,具体信息如下:
特征名称 |
特征含义 |
取值举例 |
Pregnancies |
怀孕次数 |
6 |
Glucose |
2小时口服葡萄糖耐受实验中的血浆葡萄浓度 |
148 |
BloodPressure |
舒张压 (mm Hg) |
72 |
SkinThickness |
三头肌皮褶厚度(mm) |
35 |
Insulin |
2小时血清胰岛素浓度 (mu U/ml) |
0 |
BMI |
体重指数(weight in kg/(height in m)^2) |
33.6 |
DiabetesPedigree Function |
糖尿病谱系功能(Diabetes pedigree function) |
0.627 |
Age |
年龄 |
50 |
class |
是否患有糖尿病 |
1:阳性;0:阴性 |
1. 实验内容:
2. 主要算法的程序实现:
3. 调试报告:调试过程中遇到的主要问题是如何解决的。
4.实验结果比较分析。
5. 实验总结:对实验用到的理论知识的理解,在方法设计上有何创新。
1. 实验报告应使用指定的实验报告的封面,实验名称为实验指导书中的实验名称。
2. 实验报告提交内容包括:1)实验报告的word版;2)程序源代码(单独放在一个文件夹内)。将上述2部分内容放在一个文件夹内。命名格式:班级-学号-姓名
3.实验完成后一周内,在课堂派上提交(直接上传原始文件,不要压缩)。
二:数据预处理:
代码:
"""
coding:utf-8
@author: Li Sentan
@time:2021.10.26
@file:shiyansecondpre.py
"""
#数据预处理
import pandas as pd
import numpy as np
def readcsv(path):
datas = pd.read_csv(path)
datas_Glucose = datas.Glucose
datas_length = len(datas_Glucose)
head = datas.columns
return datas ,datas_Glucose, head ,datas_length
if __name__ == '__main__':
path = 'diabetes.csv'
datas,datas_Glucose, head ,datas_length = readcsv(path)
df = pd.DataFrame(data=datas)
Gl = df['Glucose'].values
Gl0 = []
Bl = df['BloodPressure'].values
Bl0 = []
BMI = df['BMI'].values
BMI0 = []
for i in range(datas_length):
if Gl[i] <= 0:
Gl0.append(i)
Gl[i] = 0
if Bl[i] <= 0:
Bl0.append(i)
Bl[i] = 0
if BMI[i] <= 0:
BMI0.append(i)
BMI[i] = 0
Gmean = np.sum(Gl)/(len(Gl)-len(Gl0))
Bmean = np.sum(Bl)/(len(Bl)-len(Bl0))
BMImean = np.sum(BMI)/(len(Gl)-len(Gl0))
for i in Gl0:
df.loc[i,'Glucose']= Gmean
for i in Bl0:
df.loc[i,'BloodPressure'] = Bmean
for i in BMI0:
df.loc[i,'BMI'] = BMImean
a = np.std(df["Glucose"])
b = np.std(df["BloodPressure"])
c = np.std(df["BMI"])
print("normal area of Glucose:({}--->{})".format(Gmean - 3 * a,Gmean + 3 * a))
print("normal area of BloodPressure:({}--->{})".format(Bmean - 3 * b,Bmean + 3 * b))
print("normal area of BMI:({}--->{})".format(BMImean - 3 * c,BMImean + 3 * c))
for j in df["Glucose"]:
if j < Gmean - 3*a or j > Gmean + 3*a:
print(j)
print("xxxxxxxx")
for j in df["BloodPressure"]:
if j < Bmean - 3*b or j > Bmean + 3*b:
print(j)
print("xxxxxxxx")
for j in df["BMI"]:
if j < BMImean - 3 * c or j > BMImean + 3 * c:
print(j)
df.to_csv('diabetes2.csv')
原数据文件在笔者资源区可免费下载。
观察数据可知,'Glucose','BloodPressure',"BMI"这三个变量不可能为零,其他的数据咱也没有十分充足的证据说人家不对,毕竟大千世界,无奇不有,有些数据虽是离群点,但还是很真实的。
所以读取数据之后,把相应的不正确的值给它改成相应列的平均值。
然后我还打印出来了3σ范围之内的正常值和3σ之外的特殊值,结果如下:
三:决策树
代码:
"""
coding:utf-8
sorting algorithms:DecisionTreeClassifier
@author: Li Sentan
@time:2021.10.27
@file:shiyansecond1.py
"""
from sklearn.preprocessing import StandardScaler
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split
import graphviz
import pydotplus
from sklearn import tree
from IPython.display import Image
import pandas as pd
import numpy as np
import os
data = pd.read_csv("diabetes2.csv")
y = data['Class']
x = data.drop('Class', axis=1)
X = x.drop('Unnamed: 0',axis=1)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=100, train_size=0.75)
columns = X_train.columns
# ss_X = StandardScaler()
# ss_y = StandardScaler()
# X_train = ss_X.fit_transform(X_train)
# X_test = ss_X.transform(X_test)
model_tree = DecisionTreeClassifier(criterion="gini")
model_tree.fit(X_train, y_train)
y_prob = model_tree.predict_proba(X_test)[:,1]
y_pred = np.where(y_prob > 0.5, 1, 0)
count1 = 0
count2 = 0
j = 0
for i in y_test:
if y_pred[j]==i:
count1 = count1 +1
else:
count2 = count2 + 1
j = j + 1
print("the accuracy:",count1/len(y_pred))
print(y_pred)
print(y_test)
# print(model_tree.score(X_test, y_pred))
# 可视化树图
data_ = pd.read_csv("diabetes2.csv")
data_feature_name = data_.columns[1:-1]
data_target_name = np.unique(list(map(str,data_["Class"])))
os.environ["PATH"] += os.pathsep + 'G:/Graphviz/bin/'
dot_tree = tree.export_graphviz(model_tree,out_file=None,feature_names=data_feature_name,class_names=data_target_name,filled=True, rounded=True,special_characters=True)
graph = pydotplus.graph_from_dot_data(dot_tree)
img = Image(graph.create_png())
graph.write_png("out2.png")
笔者在这里调用了sklearn.tree中的DecisionTreeClassifier,首先把数据按照3:1分成训练集和测试集,因为我数据预处理用pandas.Dataframe()生成的diabeters2.csv文件中,增加了index列,
x = data.drop('Class', axis=1)
X = x.drop('Unnamed: 0',axis=1)
所以我通过删除'Class','Unnamed: 0',得到所有属性的列向量X。
model_tree = DecisionTreeClassifier(criterion="gini") #定义model_tree为DecisionTreeClassifier()的一个具体对象,criterion="gini"代表用gini系数#表示分类的不纯性,并以此来作为划分决策树的依据。 model_tree.fit(X_train, y_train) #fit()表示训练拟合模型 y_prob = model_tree.predict_proba(X_test)[:,1] #把X_test数据代入,每个数据预测分类会以概率从小到大得到类型,本数据只有两个类,所以[:,1] #表示选择第二个值,要是写成[:,0],得到模型的准确率正好是原模型的错误率。 y_pred = np.where(y_prob > 0.5, 1, 0) #其实这一步可加可不加,因为上一步已经得到0或1的值了。
接下来就可以得到准确率了。
最后,有一个决策树可视化的方法非常不错:
data_target_name = np.unique(list(map(str,data_["Class"])))
其中map()函数表示将类中的数据都变成str类型,np.unique()方法表示去掉list中重复的字符串。
class——names比较好玩,下面是它的解释:
class_names : list of strings, bool or None, optional (default=None) Names of each of the target classes in ascending numerical order. Only relevant for classification and not supported for multi-output. If True, shows a symbolic representation of the class name.
按升序排列,所以也可写成:
data_target_name = np.unique(['yes','no'])
其中的'yes'和'no'顺序可变,不影响输出结果,因为n在y之前。
最后结果如下图:
决策树可视化结果最后,提出一个探究性小问题, 训练集测试集比例改变导致模型改变,从而导致准确率改变可以理解,但是,保持训练集测试集比例不变的话,每次运行的结果准确率还是会改变的,这一点确实比较疑惑。笔者猜想,原因可能是每次运行时,系统库中的fit()方法构建函数模型的方式会改变。笔者在之后会进一步探究。
四:SVM
"""
coding:utf-8
sorting algorithms:SVM
@author: Li Sentan
@time:2021.10.27
@file:shiyansecond2.py
"""
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
def readcsv(path):
datas = pd.read_csv(path)
datas_Pregnancies = datas.Pregnancies
datas_length = len(datas_Pregnancies)
head = datas.columns
return datas ,datas_Pregnancies, head ,datas_length
#加载数据
def create_data():
path = "diabetes2.csv"
datas, datas_Pregnancies, head, datas_length = readcsv(path)
# 选取前两类作为数据
df = pd.DataFrame(data=datas)
X = df.loc[:, ("Pregnancies", "Glucose", "BloodPressure", "SkinThickness", "Insulin", "BMI",
"DiabetesPedigreeFunction", "Age")]
y = df.loc[:, 'Class']
Data = np.array(X)
Label = np.array(y)
Label = Label * 2 - 1
return Data, Label
class SVM:
def __init__(self, max_iter=768, kernel='linear'):
self.max_iter = max_iter
self._kernel = kernel
#参数初始化
def init_args(self, features, labels):
self.m, self.n = features.shape
self.X = features
self.Y = labels
self.b = 0.0
self.alpha = np.ones(self.m)
self.computer_product_matrix()#为了加快训练速度创建一个内积矩阵
# 松弛变量
self.C = 1.0
# 将Ei保存在一个列表里
self.create_E()
#KKT条件判断
def judge_KKT(self, i):
y_g = self.function_g(i) * self.Y[i]
if self.alpha[i] == 0:
return y_g >= 1
elif 0 < self.alpha[i] < self.C:
return y_g == 1
else:
return y_g <= 1
#计算内积矩阵#如果数据量较大,可以使用系数矩阵
def computer_product_matrix(self):
self.product_matrix = np.zeros((self.m,self.m)).astype(np.float)
for i in range(self.m):
for j in range(self.m):
if self.product_matrix[i][j]==0.0:
self.product_matrix[i][j]=self.product_matrix[j][i]= self.kernel(self.X[i], self.X[j])
# 核函数
def kernel(self, x1, x2):
if self._kernel == 'linear':
return np.dot(x1,x2)
elif self._kernel == 'poly':
return (np.dot(x1,x2) + 1) ** 2
return 0
#将Ei保存在一个列表里
def create_E(self):
self.E=(np.dot((self.alpha * self.Y),self.product_matrix)+self.b)-self.Y
# 预测函数g(x)
def function_g(self, i):
return self.b+np.dot((self.alpha * self.Y),self.product_matrix[i])
#选择变量
def select_alpha(self):
# 外层循环首先遍历所有满足0= 0:
j =np.argmin(self.E)
else:
j = np.argmax(self.E)
return i, j
#剪切
def clip_alpha(self, _alpha, L, H):
if _alpha > H:
return H
elif _alpha < L:
return L
else:
return _alpha
#训练函数,使用SMO算法
def Train(self, features, labels):
self.init_args(features, labels)
#SMO算法训练
for t in range(self.max_iter):
i1, i2 = self.select_alpha()
# 边界
if self.Y[i1] == self.Y[i2]:
L = max(0, self.alpha[i1] + self.alpha[i2] - self.C)
H = min(self.C, self.alpha[i1] + self.alpha[i2])
else:
L = max(0, self.alpha[i2] - self.alpha[i1])
H = min(self.C, self.C + self.alpha[i2] - self.alpha[i1])
E1 = self.E[i1]
E2 = self.E[i2]
# eta=K11+K22-2K12
eta = self.kernel(self.X[i1], self.X[i1]) + self.kernel(self.X[i2], self.X[i2]) - 2 * self.kernel(
self.X[i1], self.X[i2])
if eta <= 0:
# print('eta <= 0')
continue
alpha2_new_unc = self.alpha[i2] + self.Y[i2] * (E1 - E2) / eta # 此处有修改,根据书上应该是E1 - E2,书上130-131页
alpha2_new = self.clip_alpha(alpha2_new_unc, L, H)
alpha1_new = self.alpha[i1] + self.Y[i1] * self.Y[i2] * (self.alpha[i2] - alpha2_new)
b1_new = -E1 - self.Y[i1] * self.kernel(self.X[i1], self.X[i1]) * (alpha1_new - self.alpha[i1]) - self.Y[
i2] * self.kernel(self.X[i2], self.X[i1]) * (alpha2_new - self.alpha[i2]) + self.b
b2_new = -E2 - self.Y[i1] * self.kernel(self.X[i1], self.X[i2]) * (alpha1_new - self.alpha[i1]) - self.Y[
i2] * self.kernel(self.X[i2], self.X[i2]) * (alpha2_new - self.alpha[i2]) + self.b
if 0 < alpha1_new < self.C:
b_new = b1_new
elif 0 < alpha2_new < self.C:
b_new = b2_new
else:
# 选择中点
b_new = (b1_new + b2_new) / 2
# 更新参数
self.alpha[i1] = alpha1_new
self.alpha[i2] = alpha2_new
self.b = b_new
self.create_E()#这里与书上不同,,我选择更新全部E
def predict(self, data):
r = self.b
for i in range(self.m):
r += self.alpha[i] * self.Y[i] * self.kernel(data, self.X[i])
return 1 if r > 0 else -1
def score(self, X_test, y_test):
right_count = 0
for i in range(len(X_test)):
result = self.predict(X_test[i])
if result == y_test[i]:
right_count += 1
return right_count / len(X_test)
if __name__ == '__main__':
svm = SVM(max_iter=768)
X, y = create_data()
X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.25, random_state=100)
svm.Train(X_train, y_train)
print(svm.score(X_test, y_test))
五:knn
代码:
"""
coding:utf-8
sorting algorithms:knn
@author: Li Sentan
@time:2021.10.27
@file:shiyansecond3.py
"""
from sklearn.model_selection import cross_val_score
import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier
import pandas as pd
from sklearn.model_selection import train_test_split
data = pd.read_csv("diabetes2.csv")
y = data['Class']
x = data.drop('Class', axis=1)
x = x.drop('Unnamed: 0',axis=1)
# X_train, X_test, y_train, y_test = train_test_split(x, y, test_size=0.25, random_state=100)
# knn = KNeighborsClassifier(n_neighbors=14)
# knn.fit(X_train,y_train)
# y_pre = knn.predict(X_test)
# count1 = 0
# count2 = 0
# j = 0
# for i in y_test:
# if y_pre[j]==i:
# count1 = count1 +1
# else:
# count2 = count2 + 1
# j = j + 1
# print("the accuracy:",count1/len(y_pre))
# # print(y_pre)
# # print(y_test)
k_range = range(1, 31)
k_error = []
# 循环,取k=1到k=30,查看误差效果
for k in k_range:
knn = KNeighborsClassifier(n_neighbors=k)
# cv参数决定数据集划分比例,这里是按照5:1划分训练集和测试集
scores = cross_val_score(knn, x, y, cv=5, scoring='accuracy')
a = scores.mean()
print(a)
k_error.append(1 - a)
# 画图,x轴为k值,y值为误差值
plt.plot(k_range, k_error)
plt.xlabel('Value of K for KNN')
plt.ylabel('Error')
plt.show()
笔者特别倾心于python的其中一个原因就是它是一门很简洁灵活的编程语言,要是调用系统库函数的话基本就没几行代码了,所以在此亦能体现出来。首先,属性x,类y的构建方法和决策树是一样的,接下来:
knn = KNeighborsClassifier(n_neighbors=k) #定义一个KNeighborsClassifier()对象,n_neighbors=k代表选取k个临近值。 scores = cross_val_score(knn, x, y, cv=5, scoring='accuracy') # cv参数决定数据集划分比例,这里是按照4:1划分训练集和测试集,每次循环,scores会得到5个准确率,因为是从五份数据中从中选取一份作为测试集,所以有五种选择。scoring='accuracy'代表评价模型的方法用accuracy,即准确率。可以看出,这行代码蕴含了三步,首先计算测试样本与训练样本之间的距离,其次选出距离最近的k个点,并以这k个点中占比最多的类别作为该测试样本的类别,最后将预测值与测试集中的class进行比较,得到准确率。对每个k值得到的5个准确率进行求平均,得到结果如下:
然后对错误率进行分析,做出错误率与k的关系。结果如下:
然后,根据图形,我们可以看出,k = 13ork = 14时,错误率是比较低的,所以我们选择这两个k值,手动计算一下准确率,将后面的代码注释掉,中间的代码注释回来即可,中间的代码我用到了fit()函数,下面还有predict(),哈哈哈,完全是一时兴起,但它都没报错,并且predict()返回值是一个class数组,可以看出来,就算knn不用构建模型,但是它跟其他机器学习方法一样能够使用fit(),predict()函数,这不得不令人感慨,python的sklearn库已经做的很成熟了。你只需要在实例化对象时知道函数名称就好啦。
对比之后发现,k=14 的时候准确率比较高:
六:bayes
代码:
"""
coding:utf-8
sorting algorithms:Bayes
@author: Li Sentan
@time:2021.10.28
@file:shiyansecond4.py
"""
import math
import pandas as pd
from sklearn.model_selection import train_test_split
class Bayes(object):
def __init__(self, trainData):
self.trainData = trainData
# self.inputVector=inputVector
# model_par以字典形式存放每一个类别的方差
self.model_para = {}
count = 0
class1 = []
for i in trainData:
class1.append(i[-1])
if i[-1] == 0:
count+=1
self.a = count/len(trainData)
self.b = 1-self.a
def tarin_bayesModel(self):
# 将训练集按照类别进行提取
separated_class = self.separateByClass()
# vectors是列表,包含的是每个类别对应的向量集
for classValue, vectors in separated_class.items():
# 将每一个类别的均值和方差保存在对应的键值对中
self.model_para[classValue] = self.summarize(vectors)
return self.model_para
# 计算均值
def mean(self, numbers):
return sum(numbers) / float(len(numbers))
# 计算方差,注意是分母是n-1
def stdev(self, numbers):
avg = self.mean(numbers)
variance = sum([pow(x - avg, 2) for x in numbers]) / float(len(numbers) - 1)
return math.sqrt(variance)
# 对每一类样本的每个特征计算均值和方差,结果保存在列表中,依次为第一维特征、第二维特征等...的均值和方差
def summarize(self, vectors):
# zip利用 * 号操作符,可以将不同元组或者列表压缩为为列表集合。用来提取每类样本下的每一维的特征集合
summaries = [(self.mean(attribute), self.stdev(attribute)) for attribute in zip(*vectors)]
# 将代表类别的最后一个数据删掉,只保留均值和方差
del summaries[-1]
del summaries[0]
return summaries
# 将训练集按照类别进行提取,以字典形式存放,Key为类别,value为列表,列表中包含的是每个类别对应的向量集
def separateByClass(self):
# 字典用于存放分类后的向量集合
separated_class = {}
for i in range(len(self.trainData)):
vector = self.trainData[i]
# vector[-1]为每组数据的类别
if (vector[-1] not in separated_class):
separated_class[vector[-1]] = []
# 将每列数据存放在对应的类别下,列表形式
separated_class[vector[-1]].append(vector)
return separated_class
# 假定服从正态分布,对连续属性计算概率密度函数./>
def calProbabilityDensity(self, x, mean, stdev):
# x为待分类数据
exponent = math.exp(-(math.pow(x - mean, 2) / (2 * math.pow(stdev, 2))))
return (1 / (math.sqrt(2 * math.pi) * stdev)) * exponent
# 计算待分类数据的联合概率
def calClassProbabilities(self, inputVector):
# summaries为训练好的贝叶斯模型参数, inputVector为待分类数据(单个)
# probabilities用来保存待分类数据对每种类别的联合概率
probabilities = {}
# classValue为字典的key(类别) ,classSummaries为字典的vlaue(每个类别每维特征的均值和方差),列表形式
for classValue, classSummaries in self.model_para.items():
probabilities[classValue] = 1
# len(classSummaries)表示有多少特征维度
for i in range(len(classSummaries)):
# mean, stdev分别表示每维特征对应的均值和方差
mean, stdev = classSummaries[i]
# 提取待分类数据的i维数据值
x = inputVector[i+1]
# 计算联合概率密度
probabilities[classValue] *= self.calProbabilityDensity(x, mean, stdev)
if classValue == 0:
probabilities[classValue] *= self.a
else:
probabilities[classValue] *= self.b
# 返回概率最大的类别
prediction = max(probabilities, key=probabilities.get)
return prediction
# 计算分类准确率
def calAccuracy(testData, bayes):
correct_nums = 0
for i in range(len(testData)):
# 逐次计算每一个数据的分类类别
if testData[i][-1] == bayes.calClassProbabilities(testData[i]):
correct_nums += 1
return correct_nums
def main():
filename = 'diabetes2.csv'
df = pd.DataFrame(pd.read_csv(filename))
trainData, testData = train_test_split(df.values, test_size=0.25, random_state= 300)
bayes = Bayes(trainData)
# model为训练之后的bayes分类器模型的概率参数
model = bayes.tarin_bayesModel()
print(model)
correct_nums = calAccuracy(testData, bayes)
print("The accuracy: %f%%" % (correct_nums / len(testData) * 100.0))
if __name__ == "__main__":
main()
决策树运用分类后熵变小的思想,SVM的思路是尽可能构造出一个超平面,使不同类的数据分开,且不同类数据到该超平面的距离之和尽可能大,knn就是单纯的比较测试点与训练点之间的距离,相比之下,Bayes是一种单纯运用概率的一种方法,其思路我们高中已经接触了很多,并且做了大量的题。
对于思想,笔者用老师的两页ppt来表示,如下:
代码分析: 主要是定义的tarin_bayesModel()方法,返回值是self.model_para,为字典类型,键为Class,值为每个属性的均值,方差,如下所示:
{0.0: [(3.3207547169811322, 3.0610147534363112), (111.28048595238684, 24.20751688299456), (71.22604369297977, 11.63681692187576), (19.752021563342318, 15.386303665820186), (71.07277628032345, 102.6770459761066), (31.045049510197018, 6.6559928665440795), (0.4243099730458222, 0.29865466522797146), (31.528301886792452, 12.031541074281865)], 1.0: [(4.8585365853658535, 3.8277223818131576), (142.5091391490586, 28.964067881757458), (75.00130436229325, 12.382690628770598), (21.746341463414634, 17.396023006752408), (102.22439024390243, 143.71045369157778), (35.497094907777374, 6.922607489869842), (0.5469121951219517, 0.36766818493486086), (36.88780487804878, 10.98180748547412)]}
有了每个属性的均值,方差,我们就可以计算联合概率密度了,所以我们定义了calProbabilityDensity(),calClassProbabilities(),前者计算单个属性的概率密度,后者按类别分别计算联合概率密度,乘以对应的P(class)之后选出最大值对应的Class作为测试数据的预测类别。这句话有点绕,看官可仔细回味。
最后调用准确率,判断测试集的本身类别与其对应预测的类别的一致率,结果如下:
笔者发现,其结果与训练集测试集划分的随机数有很大关系,因为bayes本身就是一个概率学思想,其受到数据较大影响是可以理解的。