实习一
分类技术及其应用
实习题 1 基于决策树的分类算法,属性的选择采用 ID3 或 C4.5 策略,采用如下的数据
建立分类决策树。
一、 算法基本思想的描述
1)
ID3 算法通过对一个训练例集进行学习生成一棵决策树,训练例集中的每一个例子都组
织成属性—属性值对的形式。假设一个例子仅属于正例(符合被学习目标概念的例子) 或
反例(不符合目标概念的例子) 两种分类之一,例子的所有属性都为离散属性。对于每个
训练例集 Es ,如果正例的比例为 p, 则反例比例就为 q = 1 - p , 熵的公式为:Entropy
( Es ) = p * log(1 / p) + (1 - p) * log(1 / (1 - p))
2) 若 用 属 性 A 将 训 练 例 集 Es 分 组 , Entropy( Es ) 将 会 降 低 , 新 的 期 望 信 息 量 设
为:New_Entropy ( Esi , A) =Σi ∈Value ( A)(| Esi | / | Es | ) Entropy (Esi )
3) A 相对于 Es 的信息赢取 Gain ( Es , A ) , 即 Ent ropy ( Es ) 降低的数量,信息赢取越大
的属性对训练例集越有利:Gain( Es ,A) = Entropy( Es ) - New_Entropy( Esi , A)
二、 编程实现算法
/***********************************id3.h***********************************/
typedef unsigned int UINT;
typedef unsigned long ULONG;
typedef
char CHAR;
typedef unsigned char BOOL;
typedef double
REAL;
typedef
char STRING[20];
typedef struct node {
UINT tag_idx; /* ID code for attribute */
UINT dif_var_idx;
struct node *parent; /* Addess of parent node */
struct node **child; /* Address of 'on' node */
} NODE;
typedef struct ne_struct {
REAL ne;
UINT status;
} NEGENTROPY;
typedef struct matrix {
UINT width;
UINT height;
STRING **data;
} MATRIX;
enum {
INACTIVE = 0,
ACTIVE
= 1,
INVALID_TAG_IDX = 0XFFFF,
INVALID_DIF_VAR_IDX = 0XFFFF
};
#define LN_2 0.693147180559945309417
#define entropy(x) (x > 0 ? x * log(x) / LN_2 : 0.0)
/***********************************proto.h***********************************/
NEGENTROPY negentropy ( UINT column, NODE *parent );
void print_tree ( NODE *node, UINT level);
void free_tree ( NODE * );
NODE* ID3 ( NODE* parent, UINT state, UINT *used );
void err_exit ( CHAR* , UINT );
MATRIX *build_matrix ( );
void free_matrix ( );
void read_matrix ( CHAR * );
void file_size ( CHAR * );
CHAR **read_tags ( CHAR * );
void free_tags ();
UINT *Allocate_n_dif_vars ( );
UINT *Allocate_used ();
STRING **Allocate_dif_vars ();
void find_dif_vars (CHAR *file_name);
bool exsit(UINT n_dif_vars, UINT i, CHAR *ptr);
/***********************************id3.cpp***********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include "id3.h"
#include "proto.h"
/*-------------------------------------------------------------------*/
MATRIX *matrix;
/* 读进整个数据 */
CHAR **tag_names;
/* 读进属性名 */
UINT target,
/* 决策是在哪一列,即 type 是在哪一列 */
n_vars,
/* 数据有几列 */
n_samples;
/* 数据有几行 */
UINT *n_dif_vars;
/* 各列有几个不同的值 */
STRING **dif_vars; /* 各列不同的值 */
UINT MAX_N_DIF_VARS = 10; /* 假设每列最大的不同值个数为 10 */
UINT *used;
/* 在建树时用来判断哪些列被搜索过了 */
int main (int argv, char *argc[])
{
freopen("output.txt", "w", stdout);
NODE *node;
CHAR data_file[13], tag_file[13];
/* Longest file name in DOS */
UINT i;
strcpy(data_file, "input_1.txt");
strcpy(tag_file,
"input_2.txt");
/* 找数据有多少行多少列,并保存到 n_samples 和 n_vars */
file_size (data_file);
/* 分配空间给 n_dir_vars, dir_vars, 以及 used*/
n_dif_vars = Allocate_n_dif_vars ( );
dif_vars = Allocate_dif_vars ();
used = Allocate_used ( );
/* 找各列不同的值,并记录到 dif_vars[][]里 */
find_dif_vars (data_file);
/* 读进属性名 */
tag_names = read_tags (tag_file);
/* 分配空间给 matrix */
matrix = build_matrix ();
/* 读进整个数据 */
read_matrix (data_file);
/* 分类目标是最后一列 */
target = n_vars - 1;
/* 初始化各列都还没有搜索过 */
for (i=0; i
/* 输出决策树 */
print_tree(node, 0);
/* 释放空间 */
free_tags ( );
free_matrix ( );
free_tree (node);
return 0;
}
/*-------------------------------------------------------------------*/
void print_type ( NODE *node )
{
STRING **data;
NODE *_local;
UINT i;
BOOL _match;
data = matrix->data;