赞
踩
前言:出自于学校课程数据挖掘与分析布置的实验小作业,案例经典,代码注释较全,供大家参考。
题目:
现有西瓜挑选数据文件: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错误,后来以矩阵的形式输出全部数据,发现个别的数据有空格,所以在读取时,会报错。那么怎么解决呢?我的想法是我们不能修改原文件,而是重新生成一个临时文件,内部数据完全一致,我们不动原文件,相当于只是一个复制粘贴过程,实质上就是进行了一次“数据清理”。
文件获取,提取码:9vw6
界面随便弄的,不要太关注。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。