IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> C# 文本分类之朴素贝叶斯分类 -> 正文阅读

[人工智能]C# 文本分类之朴素贝叶斯分类

贝叶斯分类是一类分类算法的总称,这类算法均以贝叶斯定理为基础,故统称为贝叶斯分类。而朴素贝叶斯分类是贝叶斯分类中最简单,也是常见的一种分类方法。引用一句每篇写到朴素贝叶斯分类文章基本都会介绍的一句话。

对于机器学习和算法之类的,我是个小小白。很多东西都百思不得其解。

写这个也是一个学习的过程,为此专门买了西瓜书等其他算法书籍。emmmm,该看不懂还是看不懂。

我一开始的诉求很简单,就是想做个文本分类,查了一些文章,越看越懵,而且关于此方面的开发,大都是python写的,然后很多python又都是直接调包。。。。

关于朴素贝叶斯分类在看了几篇文章后发现,嗯,最起码我能看懂。所以就照着写了下来。最后的成果的话,我感觉还行,最起码没有太离谱。反正就是一个入门的学习,再深入的话可能要掉头发。

为了实现这个功能,简单的数据处理还是必要的,比如把北京、上海、广州、深圳定义为是城市,张三、李四、赵五定义为人名,长江、黄河、黄浦江定义为河流。这三个层次看起来还是比较好区分,最起码之间干系不大,但也不能绝对,比如有的人名叫长江等,这样的数据多了的话,会影响最终的预测结果。

当然我这里处理的数据不是这些,所以还用到了JiebaNet来对数据进行分词处理。

所以简述下这个流程就很简单,已有数据进行分类->分词处理->调用朴素贝叶斯分类算法->输入数据->预测结果。

最后提一下,虽然说代码写完了,但是是基于怎么简单怎么来的思路来做的,我甚至一度怀疑使用我这个方法来做这件事可能从根本上就是不正确的,所以说,有需要参考下就行,我的思路可能并不正确,不要在这条路上浪费过多时间。

实现功能:

    • 使用朴素贝叶斯分类实现文本分类

开发环境:

开发工具:Visual Studio 2022

.NET Framework版本:4.7.2

实现代码:

/// <summary>
    /// 朴素贝叶斯分类
    /// </summary>
    public class NaiveBayes {

        Dictionary<string, string> _types;
        List<TrainItem> _trains;
        public NaiveBayes(Dictionary<string, string> types
            , List<TrainItem> trains) {
            _types = types;
            _trains = trains;

            typesScore = new Dictionary<string, double>();
        }
        /// <summary>
        /// 待分类文本关键词(可重复,重复词有助于分类)
        /// </summary>
        private List<string> keyList = new List<string>();

        /// <summary>
        /// 类别分数
        /// </summary>
        public Dictionary<string, double> typesScore { set; get; }

        /// <summary>
        /// 计算先验概率
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private double GetPrior(string type) {
            /*
             * 先验概率P(c)=“类c下的单词总数”/“整个训练样本的单词总数”
             */

            int typeCount = GetTrainSetCount(type);
            int allCount = GetTrainSetCount();

            double result = typeCount * 1.0 / allCount;
            return result;
        }

        /// <summary>
        /// 计算似然概率 
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private double GetLikelihood(string type) {
            /*
             * P(X|c1)=P(x1|c1)P(x2|c1)...P(xn|c1)
             * P(x1|c1)="x1关键字在c1文档中出现过的次数之和+1"/"类c1下单词的总数(单词可重复)+总训练样本的不重复单词数"
             * 注:引入Laplace校准,它的思想非常简单,就是对没类别下所有划分的计数加1,解决 P(x1|c1)=0 的情况
             */
            int typeTermCount = GetTrainSetCount(type);
            int allTermCount = GetTrainSetCount();
            int sum = typeTermCount + allTermCount;

            double result = 1.0;
            int count = 0;
            //遍历待分类文本的关键字集合
            keyList.ForEach(x => {
                //计算 P(x1|c1)
                count = GetTrainSetCountForKey(type, x) + 1;
                result *= (count * 1.0 / sum);
            });
            return result;
        }

        /// <summary>
        /// 获取训练集中的关键字数量
        /// </summary>
        /// <param name="type">类别名称,为空则获取全部</param>
        /// <returns></returns>
        public int GetTrainSetCount(string type = null) {
            if(!string.IsNullOrEmpty(type)) {
                return _trains.Where(s => s.type == type).Count();
            }
            else {
                return _trains.Count();
            }
        }

        /// <summary>
        /// 获取训练集中某类别下某关键字数量
        /// </summary>
        /// <param name="type">类别</param>
        /// <param name="key">关键字</param>
        /// <returns></returns>
        public int GetTrainSetCountForKey(string type, string key) {
            int count = 0;
            //在可重复集合中寻找
            _trains.FindAll(s => s.type == type).ForEach(s => {
                count += s.textList.FindAll(t => t.Contains(key)).Count;

            });
            return count;

        }

        /// <summary>
        /// 获取最终分类结果
        /// </summary>
        /// <returns></returns>
        public string GetClassify(string content) {
            //  _tempTermList = GetTermSegment(content);//分词
            var segmenter = new JiebaSegmenter();
            keyList = segmenter.CutForSearch(content).ToList();

            /*
             * P(C|X)=P(X|C)P(C)/P(X);后验概率=似然概率(条件概率)*先验概率/联合概率
             * 
             * 其中,P(X)联合概率,为常量,所以只需要计算 P(X|C)P(C)
             * 
             * 公式:P(X|C)P(C)
             * 其中:
             * P(X|C)=P(x1|c1)P(x2|c1)...P(xn|c1)
             * P(x1|c1)="x1关键字在c1文档中出现过的次数之和 +1"/"类c1下单词的总数(单词可重复)+总训练样本的不重复单词数"
             * P(c1)=类c1下总共有单词个数(可重复)/训练样本单词总数(可重复),
             */
            double likelihood = 0f;//似然概率
            double prior = 0f;//先验概率
            double probability = 0f; //后验概率
            //1 计算每个列别的概率值
            foreach(var type in _types.Keys) {
                //计算似然概率  P(X|c1)=P(x1|c1)P(x2|c1)...P(xn|c1)
                likelihood = GetLikelihood(type);
                //计算先验概率 P(c1)
                prior = GetPrior(type);
                //计算最中值:P(X|C)P(C)
                probability = likelihood * prior;
                //保存类的最终概率值
                NoteTypeScore(type, probability);
            }
            //2 获取最大概率的类型code
            string typeCode = GetMaxSoreType();
            if(string.Equals(typeCode, string.Empty))
                return "-1";

            return typeCode;
        }

        private string GetMaxSoreType() {
            //对字典中的值进行排序
            Dictionary<string, double> soretDic = typesScore
                .OrderByDescending(x => x.Value)
                .ToDictionary(x => x.Key, x => x.Value);
            //返回第一个分数最高的类型code
            return soretDic.First().Key;

        }
        /// <summary>
        /// 记录类型得分
        /// </summary>
        /// <param name="type"></param>
        /// <param name="sore"></param>
        private void NoteTypeScore(string type, double sore) {
            typesScore[type] = sore;
        }

    }

    public class TrainItem {

        public string type { get; set; }
        public List<string> textList { get; set; }
      //  public SortedSet<string> textDistinctList = new SortedSet<string>();
        public TrainItem(string _type, List<string> _textList) {
            type = _type;
            textList = _textList;
            //textList.ForEach(s => textDistinctList.Add(s));
        }
    }
Console.WriteLine("正在加载模型...");
            var split_kindname = Properties.Resource.品种.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            var split_specname = Properties.Resource.规格.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            var split_areaname = Properties.Resource.产地.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);

            Dictionary<string, string> types = new Dictionary<string, string>
             {
                {"0","品种" },
                {"1","规格" },
                {"2","产地" },
            };
            List<TrainItem> trainSet = new List<TrainItem>
           {
                 new TrainItem("0",split_kindname.ToList()),
                 new TrainItem("1",split_specname.ToList()),
                 new TrainItem("2",split_areaname.ToList()),
            };
            Console.WriteLine("模型加载完毕...\n");

            while(true) {
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("\n请输入要检测的文本:\n");
                Console.ForegroundColor = ConsoleColor.Red;
                string input = Console.ReadLine();
                Console.WriteLine($"输入文本:{input}\n");
                Console.ForegroundColor = ConsoleColor.White;
                Console.WriteLine("正在预测结果...\n");

                NaiveBayes naiveBayes = new NaiveBayes(types, trainSet);
                string type = naiveBayes.GetClassify(input);
                Console.ForegroundColor = ConsoleColor.Green;
                if(naiveBayes.typesScore.Values.Distinct().Count() == 1) {
                    Console.WriteLine($"预测结果:未知数据");
                }
                else {
                    Console.WriteLine($"预测结果:{types[type]}");
                }

            }

实现效果:

?

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:28:48  更:2022-11-05 00:32:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 20:32:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码