Thuật toán xây dựng cây quyết định đƣợc áp dụng: Thuật toán C4.5
Thuật toán C4.5 là học cây quyết định từ một tập các ví dụ huấn luyện (training example) hay còn gọi là dữ liệu huấn luyện (training data).
Đầu vào: Một tập hợp các ví dụ. Mỗi ví dụ bao gồm các thuộc tính mô tả một tình huống, hay một đối tƣợng nào đó, và một giá trị phân loại của nó.
Đầu ra: Cây quyết định có khả năng phân loại đúng đắn các ví dụ trong tập dữ liệu huấn luyện, và hy vọng là phân loại đúng cho cả các ví dụ chƣa gặp trong tƣơng lai.
37
3.2.1 Tính độ hỗn loạn: Entropy
Đầu vào: số giá trị dƣơng và số giá trị âm của cả bảng hoặc tập thuộc tính con
Đầu ra: giá trị Entropy của bảng hoặc thuộc tính tƣơng ứng
//Tính độ hỗn loạn Entropy
private double entropy(int tot, int xau) {
int tong = tot + xau;
double tyleTot = (double)tot / tong; double tyleXau = (double)xau / tong; if (tyleTot != 0)
tyleTot = -(tyleTot) * System.Math.Log(tyleTot, 2); if (tyleXau != 0)
tyleXau = -(tyleXau) * System.Math.Log(tyleXau, 2); double _entropy = tyleTot + tyleXau;
return _entropy; }
3.2.2 Tính: GainRatio
Đầu vào: Giá trị Entropy toàn bảng, thuộc tính cần xét, danh sách giá trị, danh kết quả tƣơng ứng của thuộc tính
Đầu ra: giá trị GainRatio của thuộc tính đó
private double _tinhGainRatio(double enTropy, string attr, List<string> listValue, List<string> attrList, List<List<string>> data, List<string> resultList)
{
double splitInfo = 0.0;
double Gain; double sum = 0.0;
List<string> tem = this.laygiatricot_khonglap(attr, attrList, data); for (int i = 0; i < tem.Count(); i++)
{
int positives = 0, negatives = 0;
this.tinhsogtritotxau(attr, attrList, data, tem[i], resultList, out positives, out negatives);
double entropy = this.entropy(positives, negatives); sum += -((double)(positives + negatives) / listValue.Count()) * entropy;
//Tính splitInfo
splitInfo += ((double)(positives + negatives) /
listValue.Count()) * System.Math.Log(((double)(positives + negatives) / listValue.Count()), 2);
}
38
return Gain / splitInfo;//tra ve gia tri Gain ratio
}
3.2.3 Xây dựng cây
private void xaydungcay(ref Node nodegoc, string val, ref List<List<string>> dulieu, ref List<string> listcot, ref List<string> listketluan)
{
//thay đổi giá trị value của node
string backupVal = val; if (val != "")
val = "(" + val + ") "; int pos = sokqtot(listketluan);
//nếu đồng nhất thì gán nhãn
if (pos == listketluan.Count || pos == 0) {
Node temNode; if (pos == 0) {
temNode = new Node(val + "==> [Kết luận = " + _negative + "]", nodegoc.level + 1);
temNode.value = 0; }
else
{
Function C45_builder(tập_ví_dụ, tập_thuộc_tính)
begin
if mọi ví dụ trong tập_ví_dụ đều nằm trong cùng một lớp then return một nút lá đƣợc gán nhãn bởi lớp đó
else if tập_thuộc_tính là rỗng then
return nút lá đƣợc gán nhãn bởi tuyển của tất cả các lớp trong tập_ví_dụ
else begin
Chọn một thuộc tính P, lấy nó làm gốc cho cây hiện tại; Xóa P ra khỏi tập_thuộc_tính;
Với mỗi giá trị V của P
begin
Tạo một nhánh của cây gán nhãn V;
Đặt vào phân_vùng V các ví dụ trong tập_ví_dụ có giá trị V tại thuộc tính P;
Gọi C45_builder (phân_vùng V, tập_thuộc_tính), gắn kết quả vào nhánh V
end end end
39
temNode = new Node(val + "==> [Kết luận = " + _positive + "]", nodegoc.level + 1); temNode.value = 1; } temNode.edge_value = backupVal; temNode.isLeaves = true; nodegoc.addChild(temNode); return;
}//chưa đồng nhất thì tiếp tục phân lớp
else
{
//tính entropy của thuộc tính hiện tại
double entropyx = this.entropy(pos, listketluan.Count - pos); //tính độ đo gain ratio gán vào mảng temp
double[] temp = new double[listcot.Count]; if (temp.Length == 0) return;
for (int i = 0; i < listcot.Count; i++) {
List<string> listValue = dulieucot(listcot[i], listcot, dulieu); temp[i] = -(this._tinhGainRatio(entropyx, listcot[i], listValue,
listcot, dulieu, listketluan)); }
//tìm thuộc tính có gain ratio max để phân lớp
double max = temp[0]; int maxIdx = 0;
for (int i = 0; i < temp.Length; i++) { if (temp[i] > max) { max = temp[i]; maxIdx = i; } }
//tìm được rồi thì thêm vào con của nodegoc
Node temNode = new Node(val + listcot[maxIdx], nodegoc.level + 1); temNode.edge_value = backupVal;
temNode.attr = listcot[maxIdx]; temNode.value = temp[maxIdx]; nodegoc.addChild(temNode);
//danh sách các lớp được phân theo thuộc tính này, dựa vào giá trị khác nhau để phân lớp
List<string> valueList = laygiatricot_khonglap(listcot[maxIdx], listcot, dulieu);
foreach (string temval in valueList) {
//tạo data mới ứng với yêu cầu mới
//tạo result mới ứng với yêu cầu mới
List<List<string>> newData = new List<List<string>>(); List<string> newResultList = new List<string>(); List<string> newAttrList = new List<string>(); //lọc dữ liệu từ trong data theo giá trị value
40
newResultList = _getResultList(temval, dulieu[maxIdx], listketluan);
foreach (string attrListItem in listcot) { if (attrListItem != listcot[maxIdx]) { newAttrList.Add(attrListItem); } }
//đệ quy gọi lại hàm với nhánh dữ liệu con của thuộc tính
this.xaydungcay(ref temNode, temval, ref newData, ref
newAttrList, ref newResultList); }
} }