通过贝叶斯分类实现预测界面化

import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
import numpy as np
import re
import random
import pickle


# 定义一个朴素贝叶斯分类器类
class NaiveBayesClassifier:
    def __init__(self):
        self.word_freq_male = {}
        self.word_freq_female = {}
        self.prob_male = 0
        self.prob_female = 0
        self.vocab = set()

    # 定义 train() 方法,接收训练数据作为参数
    def train(self, training_data):
        male_names = []
        female_names = []

        # 从训练数据中分离男性和女性名字
        for line in training_data:
            name, gender = line.strip().split('\t')
            if gender == '男':
                male_names.append(name)
            elif gender == '女':
                female_names.append(name)

        # 计算先验概率
        self.prob_male = len(male_names) / len(training_data)
        self.prob_female = len(female_names) / len(training_data)

        # 计算每个字符在男性和女性名字中的频率
        for name in male_names:
            for char in name:
                if char in self.word_freq_male:
                    self.word_freq_male[char] += 1
                else:
                    self.word_freq_male[char] = 1
                self.vocab.add(char)

        for name in female_names:
            for char in name:
                if char in self.word_freq_female:
                    self.word_freq_female[char] += 1
                else:
                    self.word_freq_female[char] = 1
                self.vocab.add(char)

        # 对每个字符应用加一平滑
        for char in self.vocab:
            if char not in self.word_freq_male:
                self.word_freq_male[char] = 1
            if char not in self.word_freq_female:
                self.word_freq_female[char] = 1

        # 标准化字符频率
        male_total = sum(self.word_freq_male.values())
        female_total = sum(self.word_freq_female.values())

        for char in self.vocab:
            self.word_freq_male[char] /= male_total
            self.word_freq_female[char] /= female_total

    # 定义 predict() 方法,接收一个名字作为参数
    def predict(self, name):
        male_score = np.log(self.prob_male)
        female_score = np.log(self.prob_female)

        # 计算名字在男性和女性中的得分
        for char in name:
            if char in self.vocab:
                male_score += np.log(self.word_freq_male[char])
                female_score += np.log(self.word_freq_female[char])

        # 返回得分较高的性别
        if male_score > female_score:
            return '男'
        else:
            return '女'

    # 定义 save_model() 方法,用于将训练好的模型保存到文件
    def save_model(self, file_path):
        with open(file_path, "wb") as f:
            pickle.dump(self, f)

    # 定义一个类方法 load_model(),用于从文件加载模型
    @classmethod
    def load_model(cls, file_path):
        with open(file_path, "rb") as f:
            return pickle.load(f)

# 定义一个 Application 类,用于构建和控制 Tkinter 应用程序
class Application:
    def __init__(self, master):
        self.master = master
        master.title("名字性别判断系统")

        # 创建星空背景
        self.create_starry_background()

        # 配置 ttk 组件的样式
        style = ttk.Style()
        style.configure("TLabel", font=("Helvetica", 12))
        style.configure("TButton", font=("Helvetica", 12))

        self.frame = tk.Frame(self.canvas, padx=10, pady=10, background="#F0F0F0")

        self.frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # 创建输入框和标签
        self.label_name = ttk.Label(self.frame, text="请输入名字:", background="#F0F0F0")
        self.input_name = ttk.Entry(self.frame, width=20)
        self.label_name.grid(row=0, column=0, sticky=tk.W)
        self.input_name.grid(row=0, column=1, sticky=tk.W)

        # 创建预测按钮
        self.button_predict = ttk.Button(self.frame, text="预测性别", command=self.predict_gender)
        self.button_predict.grid(row=1, column=0, columnspan=2)

        # 创建批量预测按钮
        self.button_batch_predict = ttk.Button(self.frame, text="批量预测性别", command=self.batch_predict_gender)
        self.button_batch_predict.grid(row=2, column=0, columnspan=2)

        # 创建结果显示标签
        self.label_result = ttk.Label(self.frame, text="", background="#F0F0F0")
        self.label_result.grid(row=3, column=0, columnspan=2)

    def create_starry_background(self):
        self.canvas = tk.Canvas(self.master, width=350, height=150)
        self.canvas.pack(fill=tk.BOTH, expand=True)

        # 创建渐变背景
        for i in range(150):
            color = "#{:02x}{:02x}{:02x}".format(0, 0, int(255 * i / 149))
            self.canvas.create_line(0, i, 350, i, fill=color)

        # 创建星空背景
        for _ in range(100):
            x = random.randint(0, 350)
            y = random.randint(0, 150)
            size = random.randint(1, 3)
            self.canvas.create_oval(x, y, x + size, y + size, fill="white")

        # 适应窗口大小
        self.master.bind('<Configure>', self.update_canvas_size)

    def update_canvas_size(self, event):
        self.canvas.config(width=event.width, height=event.height)

        # 重新创建渐变背景
        for i in range(event.height):
            color = "#{:02x}{:02x}{:02x}".format(0, 0, int(255 * i / (event.height - 1)))
            self.canvas.create_line(0, i, event.width, i, fill=color)

        # 重新创建星空背景
        self.canvas.delete("star")
        for _ in range(100):
            x = random.randint(0, event.width)
            y = random.randint(0, event.height)
            size = random.randint(1, 3)
            self.canvas.create_oval(x, y, x + size, y + size, fill="white", tags="star")

    # 定义预测性别的方法
    def predict_gender(self):
        name = self.input_name.get().strip()

        if name:
            gender = nb_classifier.predict(name)
            if gender == '男':
                self.label_result.config(text=f"{name} 是男性")
            else:
                self.label_result.config(text=f"{name} 是女性")
        else:
            self.label_result.config(text="")

    # 定义批量预测性别的方法
    def batch_predict_gender(self):
        file_path = filedialog.askopenfilename()

        if file_path:
            with open(file_path, 'r', encoding='utf-8') as f:
                names = f.read().splitlines()

            results = []
            for name in names:
                gender = self.clf.predict(name)
                results.append(f"{name}:{gender}")

            with open("batch_prediction_results.txt", "w", encoding="utf-8") as f:
                f.write("\n".join(results))

            self.label_result.config(text="批量预测完成,请查看 batch_prediction_results.txt 文件")

# 读取训练数据,创建和训练朴素贝叶斯分类器的代码保持不变
# 读取训练数据
with open(r"C:\Users\14812\Desktop\NameData (2).txt", 'r', encoding='utf-8') as f:
    training_data = f.readlines()

# 创建朴素贝叶斯分类器
nb_classifier = NaiveBayesClassifier()

# 训练朴素贝叶斯分类器
nb_classifier.train(training_data)

# 保存模型到文件
nb_classifier.save_model("naive_bayes_model.pkl")


# 修改 main 函数:
def main():
    root = tk.Tk()
    app = Application(root)

    # 加载模型
    model_path = "naive_bayes_model.pkl"
    app.clf = NaiveBayesClassifier.load_model(model_path)

    # 设置窗口大小和位置
    root.geometry("350x150+400+200")

    root.mainloop()


if __name__ == "__main__":
    main()

这段代码是一个名字性别预测系统的程序,采用朴素贝叶斯分类器。程序实现了一个基于Tkinter的图形界面,用户可以输入名字,预测该名字的性别。程序分为以下几个部分:

  1. 定义了一个朴素贝叶斯分类器类(NaiveBayesClassifier)来实现训练和预测功能。

  2. 定义了一个应用类(Application),用于创建和管理Tkinter图形界面。

  3. 读取训练数据,创建并训练朴素贝叶斯分类器,然后将训练好的模型保存到文件。

  4. main() 函数中初始化Tkinter窗口,加载模型,设置窗口大小和位置,并启动Tkinter的主事件循环。

该程序的功能包括:

  • 用户输入名字,预测性别。
  • 批量预测名字性别,结果保存到一个文本文件中。

这个程序的核心是朴素贝叶斯分类器。其通过计算先验概率、字符频率等来训练模型,并基于这些概率预测名字的性别。

  1. 定义朴素贝叶斯分类器类(NaiveBayesClassifier):
# 定义一个朴素贝叶斯分类器类
class NaiveBayesClassifier:
    def __init__(self):
        # 初始化男性和女性字符频率字典
        self.word_freq_male = {}
        self.word_freq_female = {}
        # 初始化男性和女性的先验概率
        self.prob_male = 0
        self.prob_female = 0
        # 初始化词汇表
        self.vocab = set()

    # 定义 train() 方法,接收训练数据作为参数
    def train(self, training_data):
        # 初始化男性和女性名字列表
        male_names = []
        female_names = []

        # 从训练数据中分离男性和女性名字
        for line in training_data:
            name, gender = line.strip().split('\t')
            if gender == '男':
                male_names.append(name)
            elif gender == '女':
                female_names.append(name)

        # 计算先验概率
        self.prob_male = len(male_names) / len(training_data)
        self.prob_female = len(female_names) / len(training_data)

        # 计算每个字符在男性和女性名字中的频率
        for name in male_names:
            for char in name:
                if char in self.word_freq_male:
                    self.word_freq_male[char] += 1
                else:
                    self.word_freq_male[char] = 1
                self.vocab.add(char)

        for name in female_names:
            for char in name:
                if char in self.word_freq_female:
                    self.word_freq_female[char] += 1
                else:
                    self.word_freq_female[char] = 1
                self.vocab.add(char)

        # 对每个字符应用加一平滑
        for char in self.vocab:
            if char not in self.word_freq_male:
                self.word_freq_male[char] = 1
            if char not in self.word_freq_female:
                self.word_freq_female[char] = 1

        # 标准化字符频率
        male_total = sum(self.word_freq_male.values())
        female_total = sum(self.word_freq_female.values())

        for char in self.vocab:
            self.word_freq_male[char] /= male_total
            self.word_freq_female[char] /= female_total

    # 定义 predict() 方法,接收一个名字作为参数
    def predict(self, name):
        # 初始化男性和女性得分为先验概率的对数值
        male_score = np.log(self.prob_male)
        female_score = np.log(self.prob_female)

        # 计算名字在男性和女性中的得分
        for char in name:
            if char in self.vocab:
                male_score += np.log(self.word_freq_male[char])
                female_score += np.log(self.word_freq_female[char])

        # 返回得分较高的性别
        if male_score > female_score:
            return '男'
        else:
            return '女'

        # 定义 save_model() 方法,用于将训练好的模型保存到文件
        def save_model(self, file_path):
            with open(file_path, "wb") as f:
                pickle.dump(self, f)

        # 定义一个类方法 load_model(),用于从文件加载模型
        @classmethod
        def load_model(cls, file_path):
            with open(file_path, "rb") as f:
                return pickle.load(f)

 这部分代码定义了两个方法用于保存和加载训练好的模型。save_model() 方法使用 pickle 库将模型对象序列化并保存到文件,load_model() 则是一个类方法,用于从文件中加载并反序列化模型对象。

接下来,我们看一下构建和控制 Tkinter 应用程序的 Application 类: 

class Application:
    def __init__(self, master):
        self.master = master
        master.title("名字性别判断系统")

        # 创建星空背景
        self.create_starry_background()

        # 配置 ttk 组件的样式
        style = ttk.Style()
        style.configure("TLabel", font=("Helvetica", 12))
        style.configure("TButton", font=("Helvetica", 12))

        self.frame = tk.Frame(self.canvas, padx=10, pady=10, background="#F0F0F0")
        self.frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

        # 创建输入框和标签
        self.label_name = ttk.Label(self.frame, text="请输入名字:", background="#F0F0F0")
        self.input_name = ttk.Entry(self.frame, width=20)
        self.label_name.grid(row=0, column=0, sticky=tk.W)
        self.input_name.grid(row=0, column=1, sticky=tk.W)

        # 创建预测按钮
        self.button_predict = ttk.Button(self.frame, text="预测性别", command=self.predict_gender)
        self.button_predict.grid(row=1, column=0, columnspan=2)

        # 创建批量预测按钮
        self.button_batch_predict = ttk.Button(self.frame, text="批量预测性别", command=self.batch_predict_gender)
        self.button_batch_predict.grid(row=2, column=0, columnspan=2)

        # 创建结果显示标签
        self.label_result = ttk.Label(self.frame, text="", background="#F0F0F0")
        self.label_result.grid(row=3, column=0, columnspan=2)

这部分代码定义了 Application 类的构造函数,用于初始化 Tkinter 界面。首先,设置窗口标题。接着,调用 create_starry_background() 方法创建星空背景。然后,配置 ttk 组件的样式。之后,创建输入框、标签、预测按钮、批量预测按钮和结果显示标签。 

 

    def create_starry_background(self):
        self.canvas = tk.Canvas(self.master, width=350, height=150)
        self.canvas.pack(fill=tk.BOTH, expand=True)

            # 创建渐变背景
            for i in range(150):
                color = "#{:02x}{:02x}{:02x}".format(240 - i, 240 - i, 240 - i)
                self.canvas.create_line(0, i, 350, i, fill=color)

            # 在背景上随机创建星星
            for _ in range(50):
                x = random.randint(0, 350)
                y = random.randint(0, 150)
                size = random.randint(1, 3)
                self.canvas.create_oval(x, y, x + size, y + size, fill="#FFFFFF", outline="")

这部分代码定义了create_starry_background()方法。此方法创建并设置画布大小,然后使用for循环创建渐变背景。接下来,它使用另一个for循环在背景上随机创建星星。

    def predict_gender(self):
        # 获取输入的名字
        name = self.input_name.get().strip()

        # 使用朴素贝叶斯分类器进行预测
        gender = classifier.predict(name)

        # 显示预测结果
        self.label_result["text"] = f"预测结果: {gender}"

    def batch_predict_gender(self):
        # 从文件中加载测试数据
        with open("test_data.txt", "r", encoding="utf-8") as f:
            test_data = [line.strip() for line in f.readlines()]

        # 对测试数据中的名字进行预测,并与实际性别进行比较
        correct_count = 0
        for line in test_data:
            name, actual_gender = line.split("\t")
            predicted_gender = classifier.predict(name)
            if actual_gender == predicted_gender:
                correct_count += 1

        # 计算准确率并显示结果
        accuracy = correct_count / len(test_data)
        self.label_result["text"] = f"批量预测准确率: {accuracy:.2%}"

 

这部分代码定义了两个方法:predict_gender()batch_predict_gender()predict_gender()方法首先获取输入框中的名字,然后使用朴素贝叶斯分类器进行性别预测,并在结果标签中显示预测结果。

batch_predict_gender()方法从文件中加载测试数据,然后对每个名字进行预测,将预测结果与实际性别进行比较。计算预测准确率并在结果标签中显示。

if __name__ == "__main__":
    # 加载训练数据并训练朴素贝叶斯分类器
    with open("training_data.txt", "r", encoding="utf-8") as f:
        training_data = [line.strip() for line in f.readlines()]

    classifier = NaiveBayesClassifier()
    classifier.train(training_data)

    # 创建并运行 Tkinter 应用程序
    root = tk.Tk()
    app = Application(root)
    root.mainloop()

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值