前言:出自于学校课程数据挖掘与分析布置的实验小作业,案例经典,代码注释较全,供大家参考。
题目:
现有西瓜挑选数据文件:dataset.txt,编程实现朴素贝叶斯算法,并判断有如下特征的瓜是否好瓜:
青绿,稍蜷,浊响,清晰,凹陷,硬滑。
实验数据如下:
要求:
1、自行采用一种语言编程实现算法(注意:计算条件概率、判别分类等核心算法需自己编程实现)
2、用课堂例子进行正确性检验
3、用户界面友好,要考虑到输入输出
4、分析结果,说明理论分析到数值计算的注意问题
python实现
import sys
# readfile, remove_place, get_conditions, NoneException都是自己封装的方法
from FirstExp.kam import readfile, remove_place, get_conditions, NoneException
import easygui as gui
'''
这里捕获一下异常,文本中的数据如果有空格、空隙则需要处理文本信息
处理数据
数据中的空格,导致的Bug是因为取值的方法不对,
parameters["好瓜"] => parameters[col[columns - 2]] 则不会引起这样的问题
'''
try:
# 读取txt文件
df = readfile()
txt = df.data
# 获取列数
columns = txt.shape[1]
# 算好瓜与坏瓜的概率
col = txt.columns[1:columns]
# 好瓜、不好的瓜分别是多少
parameters = txt[col]
# 总体为好瓜的个数
good_num_y = parameters["好瓜"].value_counts()["是"]
# 总体不是好瓜的个数
good_num_n = parameters["好瓜"].value_counts()["否"]
# 是好瓜的概率
p_y = parameters["好瓜"].value_counts(normalize=True)["是"]
# 不是好瓜的概率
p_n = parameters["好瓜"].value_counts(normalize=True)["否"]
# 获取用户输入条件,如果用户选进行条件选择时,点击了“cancel”,或直接关闭选择框
# 则会引起异常,给出异常原因
try:
conditions = get_conditions(txt)
except NoneException as e:
print(e)
sys.exit(0)
# 判断条件是否符合要求
j = 0
# 临时变量
yes = 1
no = 1
# 使用双层遍历获取各个属性下指定类别的概率
for i in col[: columns - 2]:
while j < len(conditions):
# 满足各个条件为好瓜的数量
condition_num_y = parameters[(parameters["好瓜"] == "是") & (parameters[i] == conditions[j])].shape[0]
# 满足各个条件不是好瓜的数量
condition_num_n = parameters[(parameters["好瓜"] == "否") & (parameters[i] == conditions[j])].shape[0]
# 使用累乘获取是好瓜的概率
yes = yes * (condition_num_y / good_num_y)
# 使用累乘获取不是好瓜的概率
no = no * (condition_num_n / good_num_n)
j = j + 1
# 这里必须添加break,内层循环只需要循环一次
break
# 结果是好瓜的概率
yes = yes * p_y
# 结果不是好瓜的概率
no = no * p_n
yes_msg = "此瓜是好瓜的概率为:" + str(yes) + "\n此瓜不是好瓜的概率为:" + str(no) + "\n所以条件为:" + ",".join(conditions) + "是好瓜"
no_msg = "此瓜是好瓜的概率为:" + str(yes) + "\n此瓜不是好瓜的概率为:" + str(no) + "\n所以条件为:" + ",".join(conditions) + "不是好瓜"
if yes > no:
gui.msgbox(msg=yes_msg, title="结果", ok_button="确认")
else:
gui.msgbox(msg=no_msg, title="结果", ok_button="确认")
except KeyError:
print(remove_place(df.path))
kam.py
"""
用户选择文件,并以矩阵的形式返回
主要思想还是使用pandas库下的read函数
"""
# Author: KamTang
# Date: November 28, 2021
import os
import time
import pandas as pd
import numpy as np
import tkinter as tk
from tkinter import filedialog
import easygui as gui
class KamData(object):
"""
自定义返回类
Parameters
----------
data : 数据部分
path : 路径
"""
def __init__(self, data, path):
self.data = data
self.path = path
def readfile():
"""
读取文件
param select_path:文件路径
return: 根据文件类型,返回数据
"""
# 开启选择文件窗口
root = tk.Tk()
root.withdraw()
# 获取选择好的文件
select_path = filedialog.askopenfilename()
# 获取文件类型(后缀)
file_type = os.path.splitext(select_path)[1]
if file_type == ".csv" or file_type == ".txt":
data = pd.read_csv(select_path, encoding="utf-8")
res = KamData(data, select_path)
return res
elif file_type == ".excel":
return pd.read_excel(select_path)
else:
return "该文件类型暂时无法读取"
def remove_place(path):
"""
去除文件中的空格
Parameters
----------
path : 选择的文件路劲
Returns
-------
new_path : 重新生成的文件路径,基于你所选择的文件位置
"""
# 获取文件路径
out_path = path.rsplit("/", 1)[0]
# 获取文件类型
file_type = os.path.splitext(path)[1]
f = open(path, 'r+', encoding='utf-8')
new_f = open(out_path + "/" + time.strftime('%Y%m%d', time.localtime(time.time())) + file_type, 'w',
encoding='utf8')
for line in f.readlines():
new_str = line.replace(" ", "")
new_f.write(new_str)
f.close()
new_f.close()
# 使用字符串拼接获取新文件路径
new_path = out_path + "/" + time.strftime('%Y%m%d', time.localtime(time.time())) + file_type
print("由于选择的文件数据存在脏数据,现已重新为您生成与您选择文件数据一致的文件,路径为:")
return new_path
# 自定义异常
class NoneException(Exception):
pass
def get_conditions(read_file):
"""
:param read_file: 读取的文件
:return: 用户选择的条件
"""
# 获取列数
columns = read_file.shape[1]
# 算好瓜与坏瓜的概率
col = read_file.columns[1:columns]
# 好瓜、不好的瓜分别是多少
parameters = read_file[col]
conditions = {}
# 使用字典的形式存入各个类别
for i in col[: columns - 2]:
conditions[i] = np.unique(parameters[i].values)
# 获取所有元素下标
index = conditions.keys()
# 存入用户选择的类别
temp = []
j = 0
for i in index:
while j < len(conditions[i]):
temp.append(gui.choicebox(msg=i, choices=conditions[i], title="请选择特征"))
break
for t in range(len(temp)):
if temp[t] is None:
raise NoneException("条件存在漏选,无法分析结果。
"
)
else:
return temp
执行流程
选取文件
由于文件的部分数据带有空格,重新为用户生成一份数据一致的临时文件,提示用户选择临时文件(后面已解决该问题,数据中的空格部分不会影响整体结果)
选择瓜的属性:
结果:
总结:
此实验就是自己实现朴素贝叶斯算法,那么就需要求出各个元素的个数,对应真假概率。
我最开始是手动一个一个地将元素对应符合条件的个数取出,再求出概率。
这样没有问题,但是在代码就会显得十分冗余,而且如果数据量十分大,需要取的元素也随之增大,当然这完全能应付这个实验的,但是自己有一点点的强迫症,所以后面使用了循环处理,这样不仅使得代码更加简洁,而且增加了其可读性,也不用再定义那么多参数。
后面又觉得在读取文件时每次需要手动输入文件路径,十分麻烦,索性自己又封装了读取文件的方法,与之前的不同的是,自己封装的是通过窗口选择文件,取代了手动输入路径形式,并且还封装了“清理数据”的方法。
主要思想是如果出现KeyError异常,或者能肯定是读取的文件数据有问题,则重新生成一份文件读取。
在用第一行的标题获取文本最后一列数据时,执行的代码直接报KeyError错误,后来以矩阵的形式输出全部数据,发现个别的数据有空格,所以在读取时,会报错。
那么怎么解决呢?我的想法是我们不能修改原文件,而是重新生成一个临时文件,内部数据完全一致,我们不动原文件,相当于只是一个复制粘贴过程,实质上就是进行了一次“数据清理”。
源码(DMA文件下)
文件获取,提取码:9vw6
界面随便弄的,不要太关注。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)