分类算法 c4.5 详解

2023-05-16

C4.5是一系列用在机器学习和数据挖掘的分类问题中的算法。它的目标是监督学习:给定一个数据集,其中的每一个元组都能用一组属性值来描述,每一个元组属于一个互斥的类别中的某一类。C4.5的目标是通过学习,找到一个从属性值到类别的映射关系,并且这个映射能用于对新的类别未知的实体进行分类。

    C4.5由J.Ross Quinlan在ID3的基础上提出的。ID3算法用来构造决策树。决策树是一种类似流程图的树结构,其中每个内部节点(非树叶节点)表示在一个属性上的测试,每个分枝代表一个测试输出,而每个树叶节点存放一个类标号。一旦建立好了决策树,对于一个未给定类标号的元组,跟踪一条有根节点到叶节点的路径,该叶节点就存放着该元组的预测。决策树的优势在于不需要任何领域知识或参数设置,适合于探测性的知识发现。

    从ID3算法中衍生出了C4.5和CART两种算法,这两种算法在数据挖掘中都非常重要。下图就是一棵典型的C4.5算法对数据集产生的决策树。

比如我们判断一个人能不能结婚,那么每个人就可以作为一个具体的对象,该对象有着很多属性,比如年龄,性别,帅不帅,工作NB不,有没有女朋友,是不是富二代6个属性,而结婚也作为该对象的一个属性,而”结婚”属性就可以作为我们的预测属性!然后根据其他属性来预测我们的目标属性--结婚属性,比如说,年龄:30,性别:男,长的帅,工作不错,又女朋友,还是富二代!根据这些属性我们就可以得出该人今年可以结婚!当然这是预测出来的!这时,我们肯定有个疑问了,这是如何预测的呢?这实质上是根据我们的统计数据得出的,比如我们统计10000个人,根据这一万个人的6个属性以及目标属性(结婚)最终得出一组数据,我们用这组数据做成一个决策树!而其中这10000个人的样本我们则称为训练样本!

 

我们还是拿”打高尔夫球”这个经典的例子来作具体研究吧!该例其实就是通过一些列的属性来决定是否适合打高尔夫!刚刚说了训练样本,我们就来看看训练样本吧!图1是我用WPF做了一个简单的CRUD界面,用来把我们的样本显示的展现出来。具体看图1。。

 

image

 

 

图1  数据集

 我们从图中可以看出,该表中共有6列,而每一列中的列名对应一个属性,而我们以实践经验知道,“Day”即日期这个属性并不能帮我们预测今天是否适合去打Golf.故该属性我们就应该选择摒弃!再看该系统中的其他5给属性。很显然,图1中我用红笔画出来的属性“Play Golf”该属性就是我们的预测属性。而其他4个属性“Outlook”(天气)”、Temperature”(温度) 、“Humdity”(湿度)、“Windy”(是否刮风)这四个属性进行判断今天去 Play Golf。

那我们接下来的工作自然就是根据属性1-4得出我们的决策树了!那么我们来想想该决策树的算法,实质上其遵循一种统一的递归模式:即,首先用根节点表示一个给定的数据集(比如在这,就是我们的14个样本);然后,从根节点开始在每个节点上测试一个特定的属性,把节点数据集划分成更小的子集(这一步,比如根据属性Outlook划分,可以划分出三个子集出来,即属于Sunny的一个子集样本,属于Overcast的子集样本,属于Rainy的子集样本),该子集并用子树进行表示;该过程就开始一直进行,直到子集称为“纯的”,也就是说直到子集中的所有实例都属于同一个类别,树才停止生长。

根据算法产生的决策树: 

 

        image

 

        图2   在数据集上通过C4.5生成的决策树

 看图2,首先是根据Outlook属性进行划分,根据Outlook的三个属性值(Sunny、Overcast、Rainy)划分出了三个组合,而其中Overcast划分中的集合是“纯”的了。故此子树就停止生长了。而根据Sunny属性值划分中的样例集合1,2,8,9,11显然还不是“纯”的(该组样例中有的PlayGolf是Yes,而有的是No),故需要再次对其进行划分,直到分组中的所有样例都是“纯”的位置,才停止生长。

    算法描述

 

    C4.5并不一个算法,而是一组算法—C4.5,非剪枝C4.5和C4.5规则。下图中的算法将给出C4.5的基本工作流程:

 

    image

 

    图3  C4.5算法流程

 

    我们可能有疑问,一个元组本身有很多属性,我们怎么知道首先要对哪个属性进行判断,接下来要对哪个属性进行判断?换句话说,在图2中,我们怎么知道第一个要测试的属性是Outlook,而不是Windy?其实,能回答这些问题的一个概念就是属性选择度量。

 

    属性选择度量

 

     属性选择度量又称分裂规则,因为它们决定给定节点上的元组如何分裂。属性选择度量提供了每个属性描述给定训练元组的秩评定,具有最好度量得分的属性被选作给定元组的分裂属性。目前比较流行的属性选择度量有--信息增益、增益率和Gini指标。

 

    先做一些假设,设D是类标记元组训练集,类标号属性具有m个不同值,m个不同类Ci(i=1,2,…,m),CiD是D中Ci类的元组的集合,|D|和|CiD|分别是D和CiD中的元组个数。

 

    (1)信息增益

 

    信息增益实际上是ID3算法中用来进行属性选择度量的。它选择具有最高信息增益的属性来作为节点N的分裂属性。该属性使结果划分中的元组分类所需信息量最小。对D中的元组分类所需的期望信息为下式:

 

        image (1)

 

Info(D)又称为熵。

 

    现在假定按照属性A划分D中的元组,且属性A将D划分成v个不同的类。在该划分之后,为了得到准确的分类还需要的信息由下面的式子度量:

 

        image       (2)

 

    信息增益定义为原来的信息需求(即仅基于类比例)与新需求(即对A划分之后得到的)之间的差,即

 

        image       (3)

 

    我想很多人看到这个地方都觉得不是很好理解,所以我自己的研究了文献中关于这一块的描述,也对比了上面的三个公式,下面说说我自己的理解。

 

    一般说来,对于一个具有多个属性的元组,用一个属性就将它们完全分开几乎不可能,否则的话,决策树的深度就只能是2了。从这里可以看出,一旦我们选择一个属性A,假设将元组分成了两个部分A1和A2,由于A1和A2还可以用其它属性接着再分,所以又引出一个新的问题:接下来我们要选择哪个属性来分类?对D中元组分类所需的期望信息是Info(D) ,那么同理,当我们通过A将D划分成v个子集Dj(j=1,2,…,v)之后,我们要对Dj的元组进行分类,需要的期望信息就是Info(Dj),而一共有v个类,所以对v个集合再分类,需要的信息就是公式(2)了。由此可知,如果公式(2)越小,是不是意味着我们接下来对A分出来的几个集合再进行分类所需要的信息就越小?而对于给定的训练集,实际上Info(D)已经固定了,所以选择信息增益最大的属性作为分裂点。

 

    但是,使用信息增益的话其实是有一个缺点,那就是它偏向于具有大量值的属性。什么意思呢?就是说在训练集中,某个属性所取的不同值的个数越多,那么越有可能拿它来作为分裂属性。例如一个训练集中有10个元组,对于某一个属相A,它分别取1-10这十个数,如果对A进行分裂将会分成10个类,那么对于每一个类Info(Dj)=0,从而式(2)为0,该属性划分所得到的信息增益(3)最大,但是很显然,这种划分没有意义。

 

  (2)信息增益率

 

   正是基于此,ID3后面的C4.5采用了信息增益率这样一个概念。信息增益率使用“分裂信息”值将信息增益规范化。分类信息类似于Info(D),定义如下:

 

        image    (4)

 

这个值表示通过将训练数据集D划分成对应于属性A测试的v个输出的v个划分产生的信息。信息增益率定义:

 

        image         (5)

 

选择具有最大增益率的属性作为分裂属性。

 

    (3)Gini指标

 

    Gini指标在CART中使用。Gini指标度量数据划分或训练元组集D的不纯度,定义为:

 

        image         (6)

 

C#实现代码如下: 

计算信息增益率:

 

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace C4._5.BLL
{
    public class Entropy
    {
        public int[] statNum = new int[2];//训练统计结果:0->No  1->Yes
        public double EntropyValue = 0;
        private int mTotal = 0;
        private string mTargetAttribute = "PlayGolf";

        public void getEntropy(DataTable samples)
        {
            CountTotalClass(samples,out statNum[0],out statNum[1]);
            EntropyValue = CalcEntropy(statNum[0],statNum[1]);
        }
        /// <summary>
        /// 统计各个样本集合中所包含的目标属性Yes或者No的数目
        /// </summary>
        public void CountTotalClass(DataTable samples,out int no,out int yes)
        {
            yes = no = 0;
            foreach (DataRow aRow in samples.Rows)
            {
                if ((string)aRow[mTargetAttribute] == "Yes")
                    yes++;
                else if ((string)aRow[mTargetAttribute] == "No")
                    no++;
                else
                    throw new Exception("出错!");
            }
        }
        /// <summary>
        /// 计算熵值
        /// </summary>
        /// <returns></returns>
        public double CalcEntropy(int no,int yes)
        {
            double entropy = 0;
            double total = (double)(yes + no);
            double p = 0;
            if (no != 0)
            {
                p = no / total;
                entropy += -p * Math.Log(p,2);
            }
            if (yes != 0)
            {
                p = yes / total;
                entropy += -p * Math.Log(p, 2);
            }
            return entropy;
        }
        /// <summary>
        /// 该注释可能有问题,从属性中的样本集合中得到yes或者no的数目
        /// </summary>
        /// <param name="samples"></param>
        /// <param name="attribute"></param>
        /// <param name="value"></param>
        /// <param name="no"></param>
        /// <param name="yes"></param>
        public void GetValuesToAttribute(DataTable samples, Attribute attribute, string value, out int no, out int yes)
        {
            no = yes = 0;
            foreach (DataRow row in samples.Rows)
            {
                if ((string)row[attribute.AttributeName] == value)
                {
                    if ((string)row[mTargetAttribute] == "No")
                    {
                        no++;
                    }
                    else if ((string)row[mTargetAttribute] == "Yes")
                    {
                        yes++;
                    }
                    else
                    {
                        throw new Exception("出错");
                    }
                }   
            }
        }
        /// <summary>
        /// 计算信息收益
        /// </summary>
        /// <param name="samples"></param>
        /// <param name="attribute"></param>
        /// <returns></returns>
        public double Gain(DataTable samples, Attribute attribute)
        {
            mTotal = samples.Rows.Count;
            string[] values=attribute.values;
            double sum=0.0;
            for (int i = 0; i < values.Length; i++)
            {
                int no, yes;
                no = yes = 0;
                GetValuesToAttribute(samples,attribute,values[i],out no,out yes);
                if (yes == (yes + no) || no == (yes + no))
                {
                    sum += 0;
                }
                else
                {
                    sum += (double)(yes + no) / (double)mTotal * (-(double)yes / (double)(yes + no) * Math.Log(((double)yes / (double)(yes + no)), 2) - (double)no / (double)(yes + no) * Math.Log(((double)no / (double)(yes + no)), 2));
                }
            }
            return SplitInfo(samples,mTargetAttribute)- sum;
        }
        /// <summary>
        /// 获得targetAttribute属性下的所有属性值
        /// </summary>
        /// <param name="samples"></param>
        /// <param name="targetAttribute"></param>
        /// <returns></returns>
        private ArrayList GetDistinctValues(DataTable samples, string targetAttribute)
        {
            ArrayList distinctValues = new ArrayList(samples.Rows.Count);
            foreach (DataRow row in samples.Rows)
            {
                if (distinctValues.IndexOf(row[targetAttribute]) == -1)
                    distinctValues.Add(row[targetAttribute]);
            }
            return distinctValues;
        }
        /// <summary>
        /// 按某个属性值计算该属性的熵值
        /// </summary>
        /// <param name="samples"></param>
        /// <param name="attribute"></param>
        /// <returns></returns>
        public double SplitInfo(DataTable samples, string attribute)
        {
            ArrayList values = GetDistinctValues(samples,attribute);
            for (int i = 0; i < values.Count; i++)
            {
                if (values[i] == null || (string)values[i] == "")
                {
                    values.RemoveAt(i);
                }
            }
            int[] count=new int[values.Count];
            for (int i = 0; i < values.Count; i++)
            {
                foreach (DataRow aRow in samples.Rows)
                {
                    if ((string)aRow[attribute] == (string)values[i])
                        count[i]++;
                }
            }
            double entropy = 0;
            double total = samples.Rows.Count;
            double p = 0;
            for (int i = 0; i < values.Count; i++)
            {
                if (count[i] != 0)
                {
                    p = count[i] / total;
                    entropy += -p * Math.Log(p,2);
                }
            }
            return entropy;
        }
        /// <summary>
        /// 获得指定属性的信息增益率
        /// </summary>
        /// <param name="samples">样本集合</param>
        /// <param name="attribute"></param>
        /// <returns></returns>
        public double GainRatio(DataTable samples, Attribute attribute)
        {
            double splitInfoA = this.SplitInfo(samples,attribute.AttributeName);//计算各个属性的熵值
            double gainA = Gain(samples,attribute);//信息增益
            double gainRatioA = gainA / splitInfoA;
            return gainRatioA;
        }
    }
}

构造决策树:

public class DTree_ID3
    {
        private string mTargetAttribute = "result";
        public Entropy en = new Entropy();
        public TreeNode roots;
        /// <summary>
        /// 获得信息增益率最大的属性
        /// </summary>
        /// <param name="samples"></param>
        /// <param name="attributes"></param>
        /// <returns></returns>
        private Attribute getBestAttribute(DataTable samples,Attribute[] attributes)
        {
            double maxGain = 0.0;
            Attribute bestAttribute = null;
            foreach (Attribute attribute in attributes)
            {
                double aux = en.GainRatio(samples,attribute);
                if (aux > maxGain)
                {
                    maxGain = aux;
                    bestAttribute = attribute;
                }
            }
            return bestAttribute;
        }
        /// <summary>
        /// 判断样例集是否属于同一类,即该样例集是否是"纯"的,是则返回此属性值,否则返回Null
        /// </summary>
        /// <param name="samples"></param>
        /// <param name="targetAttribute"></param>
        /// <returns></returns>
        public string AllSamplesSameClass(DataTable samples, string targetAttribute)
        {
            DataRow row = samples.Rows[0];
            string targetValue = (string)row[targetAttribute];
            for (int i = 1; i < samples.Rows.Count; i++)
            {
                if (targetValue!=samples.Rows[i][targetAttribute].ToString())
                {
                    return null;
                }
            }
            return targetValue;
        }
        /// <summary>
        /// 获得属性的目标属性的值(解释有可能错误)
        /// </summary>
        /// <param name="samples"></param>
        /// <param name="targetAttribute"></param>
        /// <returns></returns>
        private ArrayList GetDistinctValues(DataTable samples, string targetAttribute)
        {
            ArrayList distinctValues = new ArrayList(samples.Rows.Count);
            foreach (DataRow row in samples.Rows)
            {
                if (distinctValues.IndexOf(row[targetAttribute]) == -1)
                    distinctValues.Add(row[targetAttribute]);
            }
            return distinctValues;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="samples"></param>
        /// <param name="targetAttribute"></param>
        /// <returns></returns>
        private object GetMostCommonValue(DataTable samples, string targetAttribute)
        {
            ArrayList distinctValues = GetDistinctValues(samples,targetAttribute);
            int[] count=new int[distinctValues.Count];
            foreach (DataRow row in samples.Rows)
            {
                int index = distinctValues.IndexOf(row[targetAttribute]);
                count[index]++;
            }
            int MaxIndex = 0;
            int MaxCount = 0;
            for (int i = 0; i < count.Length; i++)
            {
                if (count[i] > MaxCount)
                {
                    MaxCount = count[i];
                    MaxIndex = i;
                }
            }
            return distinctValues[MaxIndex];
        }
        /// <summary>
        /// 构造决策树
        /// </summary>
        /// <param name="samples">样本集合</param>
        /// <param name="targetAttribute">目标属性</param>
        /// <param name="attributes">该样本所含的属性集合</param>
        /// <returns></returns>
        private TreeNode BuildTree(DataTable samples, string targetAttribute, Attribute[] attributes)
        {
            TreeNode temp = new TreeNode();
            //如果samples中的元祖是同一类C
            string c = AllSamplesSameClass(samples,targetAttribute);
            if (c != null)   //返回N作为叶节点,以类C标记
                return new TreeNode(new Attribute(c).AttributeName + c);
            
            //if attributes为空,then
            if (attributes.Length == 0)//返回N作为叶子节点,标记为D中的多数类,多数表决
            {
                return new TreeNode(new Attribute(GetMostCommonValue(samples,targetAttribute)).AttributeName);
            }
            //计算目标属性的熵值,即PlayGolf的熵值
            mTargetAttribute = targetAttribute;
            en.getEntropy(samples);
            //找出最好的分类属性,即信息熵最大的
            Attribute bestAttribute = getBestAttribute(samples,attributes);
            //标记为节点root
            DTreeNode root = new DTreeNode(bestAttribute);
            temp.Text = bestAttribute.AttributeName;

            DataTable aSample = samples.Clone();
            //为bestAttribute的每个输出value划分元祖并产生子树
            foreach (string value in bestAttribute.values)
            {
                aSample.Rows.Clear();
                //aSamples为满足输出value的集合,即一个划分(分支)
                DataRow[] rows = samples.Select(bestAttribute.AttributeName+"="+"'"+value+"'");
                foreach (DataRow row in rows)
                {
                    aSample.Rows.Add(row.ItemArray);
                }
                //删除划分属性
                ArrayList aArributes = new ArrayList(attributes.Length-1);
                for (int i = 0; i < attributes.Length; i++)
                {
                    if (attributes[i].AttributeName != bestAttribute.AttributeName)
                    {
                        aArributes.Add(attributes[i]);
                    }
                }
                //如果aSample为空,加一个树叶到节点N,标记为aSample中的多数类
                if (aSample.Rows.Count == 0)
                {
                    TreeNode leaf = new TreeNode();
                    leaf.Text = GetMostCommonValue(samples, targetAttribute).ToString() + "(" + value + ")";
                    temp.Nodes.Add(leaf);
                }
                else  //加一个由BulidTree(samples,targetAttribute,attributes)返回的节点到节点N
                {
                    DTree_ID3 dc3 = new DTree_ID3();
                    TreeNode ChildNode = dc3.BuildTree(aSample,targetAttribute,(Attribute[])aArributes.ToArray(typeof(Attribute)));
                    ChildNode.Text += "(" + value + ")";
                    temp.Nodes.Add(ChildNode);
                }
            }
            roots = temp;
            return temp;
        }
        public TreeNode MountTree(DataTable samples, string targetAttribute, Attribute[] attributes)
        {
            return BuildTree(samples, targetAttribute, attributes);
        }
    }

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分类算法 c4.5 详解 的相关文章

  • 15 KVM虚拟机配置-体系架构相关配置

    文章目录 15 KVM虚拟机配置 体系架构相关配置15 1 概述15 2 元素介绍15 3 AArch64架构配置示例15 4 x86 64架构配置示例 15 KVM虚拟机配置 体系架构相关配置 15 1 概述 XML中还有一部分体系架构相
  • 16 KVM虚拟机配置-其他常见配置项

    文章目录 16 KVM虚拟机配置 其他常见配置项16 1 概述16 2 元素介绍16 3 配置示例 16 KVM虚拟机配置 其他常见配置项 16 1 概述 除系统资源和虚拟设备外 xff0c XML配置文件还需要配置一些其他元素 xff0c
  • windows查看默认编码类型

    xfeff xfeff 开始 cmd 运行chcp 你会得到一个数 例 xff1a 如936 xff0c 那就是GBK简体中文 ANSI代码页为1252 xff0c 日文代码页为932
  • 三、@PathVariable

    3 1 64 PathVariable 映射 URL 绑定的占位符 带占位符的 URL 是 Spring3 0 新增的功能 xff0c 该功能在SpringMVC 向 REST 目标挺进发展过程中具有里程碑的意义通过 64 PathVari
  • 走进CSDN

    走进CSDN 关注CSDN不久 xff0c 最近浏览的次数增多 xff0c CSDN的资讯刚开始基本上看的懂的不多 xff0c 专业名词扎堆的论坛 xff0c CSDN的氛围个人感觉挺好的 xff0c 一群俗称 程序员 的人聚集讨论问题 x
  • B端产品经理基本工作流程

    产品岗位必备素质 产品是一个门槛较低的岗位 xff0c 是一个看起来很容易 xff0c 做起来各个地方都是bug的岗位 产品需要更多的是软实力 xff0c 把握产品的方向 xff0c 目标用户是谁 xff0c 场景是什么 xff0c 达到怎
  • Mac实用的远程ssh连接工具( Royal TSX安装及使用)

    Mac实用的远程ssh连接工具 Royal TSX安装及使用 1 下载地址 https www royalapps com ts mac download 2 如何连接远程服务器 2 1 首先下载插件Terminal 2 2 然后创建新的D
  • 尝试VC控制外部程序

    这两天尝试VC控制外部程序呢 xff0c 慢慢完善 在参考了网络学习以后 xff0c 简单做了以下工作 xff1a 期间用了spy 43 43 器件 void CVCControlDlg OnStartreader 启动朗读女 TODO A
  • Windows Sever 2012 R2设置组策略对“不显示最后的登录名”选项已启用

    Windows Sever 2012 R2设置组策略对 不显示最后的登录名 选项已启用 作者 xff1a 我道梦 关注我的CSDN博客 xff0c 更多笔记知识还在更新 xff01 设置组策略启用 不显示最后的登录名 后 xff0c 系统将
  • Ubuntu22.04.1 & WIN11 双系统+双硬盘 grub启动项中无WIN11开机引导

    本机UEFI 43 GPT安装的双系统 xff0c 两块固态硬盘 xff0c 两个系统各自使用自己的硬盘分区 xff0c xff08 选择的全盘安装在新硬盘 xff0c 没有自定义分区 xff0c 所以安装的时候也没有提示与当前window
  • tightvnc,tightvnc软件介绍,详细介绍

    tightvnc一款用于windows操作系统的应用软件 xff0c 是一款远程控制软件 出门在外忘了带档案怎么办 xff1f FTP server 上头忘了开帐号怎么办 xff1f 这些麻烦的问题其实都可以靠 VNC 解决 tightvn
  • OpenCore-EFI-配置模版(持续更新)

    前言 随着OpenCore日臻完善 xff0c 将在以后会更多的用于黑苹果的安装 同时 xff0c 在各位大佬的大力支持与推广 xff0c 各种入门 xff0c 进阶教程的推出 xff0c OpenCore已经从神界降临到人间 逐渐为普通黑
  • OpenCore(OC)引导开机声音与图形界面设置

    关键字 xff1a OC xff1b OpenCore xff1b 引导 xff1b 开机声音 xff1b 图形界面 下面的设置基于OpenCore0 5 8 04 10编译版与1 22 0 0版OpenCore Configurator
  • The BMJ研究:现有的新冠病毒诊断AI模型,几乎毫无用处

    图片出处 xff1a unsplash 本文作者 xff1a 朱演瑞 新型冠状病毒对全球健康造成了严重的威胁 xff0c 为了减轻医疗保健系统的负担 xff0c 也给患者提供最佳的护理 xff0c 高效的诊断和疾病预后信息问题亟待解决 理论
  • 06-Docker-Centos 7.2 (Vmware最小化安装)之一篇搞定hyperledger/fabric的e2e_cli测试运行所遇到的ERROR总结

    bug产生原因分析如下 xff1a 1 系统过于单纯或复杂 xff08 即最小化安装与全部安装以及自行安装了很多软件 xff09 xff0c 很多命令和工具无法使用和执行或冲突 2 自己操作失误 xff0c 敲错代码 xff08 关键词和语
  • 秒懂Java之方法引用(method reference)详解

    版权申明 非商业目的注明出处可自由转载 出自 xff1a shusheng007 相关文章 xff1a 秒懂Java之深入理解Lambda表达式 文章目录 概述使用条件使用场景如何使用方法引用的类型调用类的静态方法调用传入的实例参数的方法调
  • 产品设计中关于思考力那些事

    这周的面试 xff0c 对我自己来说 xff0c 更像是一种迭代反思 从做什么怎么做 xff0c 到为什么做 xff0c 的一种强制思考 一方面是入行时间短 xff0c 另一方面是公司产品业务主导 xff0c 相对不需要产品去思考 xff0
  • 永不磨灭的设计模式(有这一篇真够了,拒绝标题党)

    版权申明 非商业目的注明出处可自由转载 出自 xff1a shusheng007 文章目录 概述定义分类创建型 xff08 creational xff09 结构型 xff08 structural xff09 行为型 xff08 beha
  • shusheng007编程手记

    版权申明 非商业目的注明出处可自由转载 出自 xff1a shusheng007 文章目录 概述工具篇IntelliJ IDEA在Idea中下载源码时 xff0c 报无法下载源码 Postman使用Postman发送Post请求服务端报得到
  • SpringBoot如何整合RabbitMQ

    版权申明 非商业目的注明出处可自由转载 出自 xff1a shusheng007 文章目录 概述rabbitmq简介SpringBoot整合安装rabbitmq初级用法高级用法配置交换器与队列发送消息消费消息测试 总结 概述 好久没有写博客

随机推荐

  • 秒懂SpringBoot之@Async如何自定义线程池

    版权申明 非商业目的注明出处可自由转载 出自 xff1a shusheng007 文章目录 概述异步初探线程池ThreadPoolExecutorThreadPoolTaskExecutor 验证线程池配置拒绝策略为AbortPolicy拒
  • 秒懂SpringBoot之参数验证全解析(@Validated与@Valid)

    版权申明 非商业目的注明出处可自由转载 出自 xff1a shusheng007 文章目录 概述实例SpringBoot 验证概述引入依赖使用相关注解标记使用 64 Valid标记统一处理异常 高级用法复杂对象参数验证基本类型参数验证Ser
  • 如何添加本地JAR文件到Maven项目中

    版权申明 非商业目的可自由转载 博文地址 xff1a 出自 xff1a shusheng007 相关文章 xff1a 秒懂Java序列化与反序列化 秒懂 Java注解类型 xff08 64 Annotation xff09 秒懂Java多线
  • 秒懂Java泛型

    版权申明 非商业目的可自由转载 博文地址 xff1a https blog csdn net ShuSheng0007 article details 80720406 出自 xff1a shusheng007 文章目录 概述什么是泛型为什
  • 实际项目中如何使用Git做分支管理

    版权申明 非商业目的注明出处可自由转载 出自 xff1a shusheng007 相关文章 Git日常开发常用命令汇总 文章目录 前言概述Git的基本使用方法使用Git管理项目的方式主分支支持分支总结图 总结 前言 记得刚工作的时候根本不知
  • 秒懂Java代理与动态代理模式

    版权申明 非商业目的可自由转载 博文地址 xff1a https blog csdn net shusheng0007 article details 80864854 出自 xff1a shusheng007 设计模式汇总篇 xff0c
  • 秒懂Java动态编程(Javassist研究)

    版权申明 非商业目的可自由转载 博文地址 xff1a https blog csdn net ShuSheng0007 article details 81269295 出自 xff1a shusheng007 概述什么是动态编程 反射动态
  • B端项目整体设计流程

    一 B端产品的能力图谱 1 逻辑思维与抽象能力 2 技术知识储备 3 复杂项目管理能力 xff1a 沟通能力 执行能力 团队协助能力 组织协调能力 4 业务与经营管理知识 二 B端产品设计流程 1 业务调研 a 明确调研目标 战略层 xff
  • Git日常开发常用命令汇总

    版权申明 非商业目的z注明出处可自由转载 博文地址 xff1a https blog csdn net ShuSheng0007 article details 89642945 出自 xff1a shusheng007 相关文章 实际项目
  • in为什么慢

    IN为什么慢 xff1f 在应用程序中使用子查询后 xff0c SQL语句的查询性能变得非常糟糕 例如 xff1a SELECT driver id FROM driver where driver id in SELECT driver
  • 漫谈IT项目团队管理心得

    漫谈IT项目团队管理心得 如果在软件项目实施中选出最难解决的几个问题 xff0c 那么管理问题一定名列前茅 在管理问题中 xff0c 团队管理又是其中的难点 一个项目管理的好坏 xff0c 很大程度就体现在团队的建设和管理上 团队管理涉及到
  • error: [Errno 111] Connection refused

    用户cdh安装 hadoop的过程中 xff0c 启动CM xff0c 日志出现连接错误 cloudera 需要配置好dns xff0c 他是通过dns解析主机名来访问的 xff0c 这里可能dns解析有问题 xff0c 所以最好是把 us
  • dbca提示command not found

    1 dbca提示command not found 如果在database软件安装无错误后 xff0c 应该是环境变量找不到 2 检查环境变量 xff0c 果然有11 333 xff0c 这是远程粘贴板的问题吧 3 修改后 xff0c so
  • IT如何转为销售

    销售 xff0c 在很多人眼中是不入流的职业 不少人认为 xff0c 没有一技之长或没有能力才退而求其次去做一个销售 然而 xff0c 年薪50万的技术工程师 xff0c 马仁业为什么会放弃大家眼中神一样的职业 xff0c 去做一个没有底薪
  • MYSQL单行长度不能超过 65535

    报错 xff1a Row size too large The maximum row size for the used table type not counting BLOBs is 65535 mysql属于关系型 xff0c 行式
  • jdbcTemplate.batchUpdate在批量执行的时候,性能差没有效果,看看怎么解决的。

    我用的阿里druid数据库连接池 xff08 其实这个和连接池毛线关系没得 xff09 xff0c 创建jdbctemplate在执行insert 15000条数据时 xff0c 我发现还是30条 xff0c 20条 xff0c 35条这样
  • rabbit-mq 本地环境搭建

    一 xff1a 安装RabbitMQ需要先安装Erlang语言开发包 xff0c 直接下载地址 xff1a http erlang org download otp win64 18 3 exe 尽量安装时不选择C盘 xff0c 避免操作系
  • oracle小数点前面没有0,纠结解惑

    一1 天前台人找到我 xff0c 说我们安装的数据库有问题 xff0c 为什么小数点前面是0就不显示呢 xff0c 我去看了一下 xff0c command窗口要显示 SQL gt create table ml test num numb
  • 网监后台管理系统设计思路

    本次做的是网监系统saas服务平台的后台管理系统 xff0c 不涉及复杂功能逻辑 就是从菜单 模板 系 统 组织架构 角色 用户的设计思路 产品需求 xff1a 在各个省市网监系统的数量不断增长 xff0c 且系统逻辑和功能模块大致相同 x
  • 分类算法 c4.5 详解

    C4 5是一系列用在机器学习和数据挖掘的分类问题中的算法 它的目标是监督学习 xff1a 给定一个数据集 xff0c 其中的每一个元组都能用一组属性值来描述 xff0c 每一个元组属于一个互斥的类别中的某一类 C4 5的目标是通过学习 xf