UCI數據集詳解及其數據處理(附148個數據集及處理代碼)

介紹圖
摘要:本文對機器學習中的UCI數據集進行介紹,帶你從UCI數據集官網出發一步步深入認識數據集,並就下載的原始數據詳細講解了不同類型的數據集整理如何通過程序進行整理。爲了方便使用,博文中附上了包括數據集整理及數據預處理在內的所有代碼及處理好的數據集,同時對代碼進行了解釋,其要點如下:

\color{#4285f4}{點}\color{#ea4335}{擊}\color{#fbbc05}{跳}\color{#4285f4}{轉}\color{#34a853}{至}\color{#ea4335}{博}\color{#4285f4}{文}\color{#ea4335}{涉}\color{#fbbc05}{及}\color{#4285f4}{的}\color{#34a853}{全}\color{#ea4335}{部}\color{#fbbc05}{文}\color{#4285f4}{件}\color{#34a853}{下}\color{#ea4335}{載}\color{#fbbc05}{頁}


前言

  UCI\color{#4285f4}{U}\color{#ea4335}{C}\color{#fbbc05}{I}\color{#4285f4}數據集作爲機器學習算法比較中的絕對經典經常出現在大多數論文或研究中。爲了驗證機器學習算法性能,UCI數據集通常用作爲通用數據集,但官網提供的原始數據可能有格式不一致、缺失數據、包含特殊字符等問題,通常不能直接用於算法程序中,數據集的查找、下載、整理等可能會給初學者帶來一定困擾。

UCI官網配圖
  對於數據集的查找整理確實是件費時費力的事情,是不是總有“論文就一篇,數據找半天”的問題?這裏就來探討下數據集整理的那些事。其實早前作者就寫了一篇關於UCI數據集處理的博文:UCI數據集整理(附論文常用數據集)介紹瞭如何用程序整理數據集,這裏會更加深入地介紹不同類型的數據集處理方法及數據預處理。本文較長建議結合右側的目錄閱讀。


1.UCI數據集介紹

  這一節先從UCI數據集官網出發介紹數據集的屬性、格式等信息,在我的博文:UCI數據集整理(附論文常用數據集)中也有部分介紹,對數據集熟悉或想看數據處理代碼乾貨的朋友也可以直接跳轉至下一節。下面先看一下對UCI數據集的介紹。

1.1 UCI數據集官網介紹

  UCI\color{#4285f4}{U}\color{#ea4335}{C}\color{#fbbc05}{I}\color{#4285f4}(University of California Irvine)數據集是美國加州大學歐文分校提出的一種適合模式識別和機器學習方向的開源數據集,很多學者選擇使用UCI上的數據集來驗證自己所提算法的正確性。博文寫作時已擁有488個數據集,數據集還在不斷擴充中,這些數據集主要分爲二值分類問題、多分類問題以及迴歸擬合問題。UCI數據集提供了各個數據集的上主要屬性,可以根據自己提出的各類算法在其數據集上做實驗結果論證,證明自己所提算法的合理性。
uci官網
UCI數據集官網地址:https://archive.ics.uci.edu/ml/index.php
UCI數據集數據地址:https://archive.ics.uci.edu/ml/datasets.php

  我在下圖所示的UCI數據集官網截圖中對其頁面主要部分進行了標註,可以看出主頁中主要包括了數據集頁面入口、最新數據集、經典數據集及數據集的最近消息等。數據集頁面入口提供了進入官網查看全部數據集的鏈接,爲了方便用戶查找在「最新數據集」和「經典數據集」區域整理了最新收錄以及引用最多的幾個數據集。如果只是簡單測試下代碼,直接點擊頁面上提供的數據集鏈接下載幾個數據集就可以了,如果還需要更多數據集那就進入數據集頁面入口,該頁面發佈有全部的數據集。

首頁介紹
  下圖(圖中頁面已翻譯)所示的全部數據集頁面是一個按類型排列的數據表,可以按照數據集名稱、任務類型、屬性類型、數據類型等進行排列查找,點擊想要的數據集鏈接可進入該數據集詳情頁。值得注意的是,右上角有一個搜索框,用戶可以通過輸入數據集名字搜索數據集,不過比較可惜親測下來該搜索在沒有外網VPN的加持下可能不能打開網頁 (當然不能用的還有搜數據集的利器——谷歌數據集搜索)。
在這裏插入圖片描述
  現在以官網數據集頁面中的Adult(成年人收入)數據集爲例,介紹以下數據集詳情頁面,點擊鏈接進入Adult數據集頁面,頁面主要情況如下圖1.1.1所示。對於需要特別關注的地方我已經用紅色標記,主要包括數據集下載頁面鏈接、數據集說明下載鏈接、數據量、屬性數、是否確實數據及屬性信息。當然其他的信息不可說沒有必要,當我們要選用某個數據集進行測試時,瞭解更多的相關信息有助於更好根據數據情況對算法做出調整。頁面最後面的相關論文和引用文獻也能幫助瞭解專業情況。

adult數據集頁面

圖1.1.1 Adult數據集頁面

這裏對上面提及的幾個重要部分做個簡介:

  • 數據量(Number of Instances):或稱實例數,表示數據集有多少行數據。
  • 屬性數(Number of Attributes):表示數據集每行有多少個特徵屬性,決定了數據集複雜程度。
  • 屬性信息(Attribute Information):這裏介紹了數據集的分類類別,及每個屬性表示的意義。例如上圖數據集中介紹了成年人收入的兩種分類類別:> 50K, <= 50K,屬性情況:年齡、工作類別、教育程度等14個屬性。
  • 是否缺失數據(Missing Values):這體現了數據集中是否有某些數據缺失,如有缺失,則應特別注意在數據處理時需要補充數據或刪除無效數據。
  • 屬性類型(Attribute Characteristics):一般有Categorical(類別型), Integer(整數型), Real(實數型)這三種。值得注意的是,如果這一欄中有Categorical型表示該數據集中可能會包含字符串,處理數據時需要用對應數字代替。

1.2 數據集文件認識

下載鏈接
  如上圖所示,點擊Data Folder進入Adult數據集文件下載目錄頁面,可以看到該數據集的文件目錄如下圖所示。點擊下載鏈接即可下載該數據集,Adult數據集已經劃分好訓練和測試數據集(一般的數據集未劃分則只有一個數據文件),所以這裏需要分別下載下圖所示的兩處文件,如下在鏈接上右鍵,點擊“鏈接另存爲”即可下載文件。

數據集下載
  上面下載的文件格式類型爲data型,該文件在MATLAB中可以直接打開(也可以右擊選擇打開方式爲記事本打開),打開的文件內容如下圖(加的紅線分割左側爲屬性,右側爲標記):

Adult文件內容

圖1.2.1 Adult文件數據詳情

  可以看到文件中的數據中既有英文字符串又有整數,果然同前面介紹頁中的“屬性類型”顯示的那樣爲Categorical型和Integer性。剛學習的朋友可能不太能明白這一堆數據裏面到底是些什麼,這一堆奇怪的數據真的能被算法直接計算嗎?其實在上面一小節中已經有所提及,前面我們看到Adult數據集詳情頁面中“Attribute Information(屬性信息)”那一欄(如圖1.2.2)介紹的該數據集的類別有兩個:> 50K, <= 50K,也就是收入超過50K和不超過50K兩類。這說明每行最後面的那一欄是就標籤,這實際是一個二分類任務的數據集,每行前面的14個數據分別是年齡、工作類別、教育程度等14個屬性,如下圖1.2.2:

屬性信息

圖1.2.2 Adult數據集屬性信息

  再仔細看圖1.2.1中的數據,結合圖1.2.2可以知道每行的第一個屬性表示的是年齡,它是個連續的整數型數據。而第二個屬性爲工作類別,它是一個英文字符串表示的字符型離散值,在整個數據集中這一屬性實際可能取值是:Private, Self-emp-not-inc, Self-emp-inc, Federal-gov, Local-gov, State-gov, Without-pay, Never-worked這幾個工作類別,也就是前面說的Categorical型,同樣的還有第4,6,7…個屬性表示的教育程度、婚姻狀況、職業等等。這爲我們後面用程序整理數據集提供了思路,既然是有限類別的,那我們就可以用類似1,2,3…這樣的數字代替對應的英文字符串從而轉化爲一個純數字的數據文件供算法程序使用了,後面一章將詳細介紹。

  前面的圖1.2.1中展示的是數據集前12行的數據,但如果我們再仔細瀏覽後面的數據還有一些值得注意的地方,如下圖1.2.3標記的第15行數據。

adult缺失數據信息

圖1.2.3 Adult數據集缺失數據部分

  該行數據的第14個屬性表示爲“?”意味着該處數據缺失,也就是國籍不詳(第14個屬性表示國籍),此外還有其他少數的幾行有部分數據缺失。這和前面圖1.1.1中的描述的“存在數據缺失”相符,數據缺失在機器學習中也很常見,因爲數據的採集過程可能比較複雜,有些數據缺失在所難免。對於缺失的數據我們要做的也很簡單,那就是“補上還能用的數據,或者刪掉無效的數據”就可以了,下一章會詳細講述。

存在缺失數據

1.3 不同類型的UCI數據集

  上面兩個小節以Adult數據集爲例從頭到尾介紹了一遍如何認識和理解數據集文件中的數據,讀者應該對UCI數據集有了一個基本認識。其實Adult數據集算是一個比較“複雜麻煩”的數據集了,大多的數據集不會有那麼多英文字符和數據缺失。大多的數據集屬性爲數字,類別標籤可能是數字或英文字符,數據也比較完整是無需我們處理缺失數據的。在我的博文《UCI數據集整理(附論文常用數據集)》中也有介紹,有興趣的可以點過去看一下。之所以說得這麼複雜是因爲這個數據集幾乎包含了UCI數據集中的所有可能的“麻煩問題”。接下來簡單列舉總結下UCI數據集文件中數據的幾種類型,這將決定了我們後面採用怎樣的方式整理數據集。

  爲了後面敘述方便,原諒我不太專業地根據文件中的數據是否部分包含英文字符、是否爲純數字、是否缺失數據將其分爲三個難度:“純數字、無缺失”,“部分英文字符、無缺失”,“部分or全部英文字符、有缺失”來分別介紹。當然還有“純數字、有缺失”等組合,但是也可以參考第三種對缺失的處理方式,爲了避免重複敘述這裏就省略了。這三種情況的代表數據集有Glass數據集Abalone數據集Adult數據集,三個數據集的部分數據截圖如下:

glass數據集
abalone數據集
Adult數據集
  上面的三個數據集建議讀者按照前面兩小節的方法對照每個數據集詳情頁面上的介紹再研究一下,對於這三個數據集的介紹這裏就不一一展開了,下面一節將以這三個數據集的整理爲例講述如何通過程序整理這三種數據集文件。


2. 不同數據集的整理

  這一節就上節提到的UCI數據集中常見三種文件數據類型如何通過程序整理進行詳細介紹。首先之所以需要整理數據集,是因爲我們下載的UCI數據集文件常常可能含有英文字符串、缺失數據、存在無效數據等問題或者下載下來的數據集文件格式不一致導致我們無法通過統一的程序使用它。那麼什麼樣的數據格式是我們想要的呢?

  還是以Adult數據集爲例,其中的英文字符需要換成對應的數字表示,缺失的數據需要補充,另外數據集的分類標記:> 50K, <= 50K分別用數字> 0, 1代替並由最後一列移至首位(標記一般在數據首位,也可以放在末尾)。Adult數據集的原始數據文件與整理完成後的數據文件對比如下圖所示:

adult原始數據

圖2.1 Adult數據集原始數據

Adult整理後的數據

圖2.2 Adult數據集整理後的數據

  很明顯整理後的數據乾淨整潔、易於讀取,而且在部分屬性特徵上更加適合機器學習算法處理,其中每行數據的第一個數字爲分類標記。類似圖2.2正是我們需要的數據格式,爲了統一使用方便,博文中的數據集都整理爲這種形式。接下來從易到難分別介紹“純數字、無缺失”,“部分英文字符、無缺失”,“部分or全部英文字符、有缺失”三種情況下的數據如何通過程序整理,以下部分全部採用Matlab\color{#4285f4}{M}\color{#ea4335}{a}\color{#fbbc05}{t}\color{#4285f4}{l}\color{#34a853}{a}\color{#ea4335}{b}編程實現。

2.1 “純數字、無缺失”數據集

  以Glass數據集爲例,首先在Glass數據集下載頁下載Glass原始數據集,其數據文件部分數據如下圖所示。其特點爲純數字,無缺失和特殊數據因此無需特殊處理技巧。由Glass數據集詳情頁上的介紹,該數據集爲一個分類數爲6,屬性數爲9的數據集。

glass數據集
  在下載的數據文件存放路徑處新建Matlab\color{#4285f4}{M}\color{#ea4335}{a}\color{#fbbc05}{t}\color{#4285f4}{l}\color{#34a853}{a}\color{#ea4335}{b}程序,創建一個命名爲main.m的文件,並在編輯器鍵入如下代碼:

% glass
% author: wuxian, website: https://wuxian.blog.csdn.net
clear;
clc;

data_name = 'glass';
fprintf('開始處理數據集: %s ...\n', data_name);

n_entradas= 9; % 屬性數
n_clases= 6; % 類別數
n_patrons(1)= 214; % 數據量(行數)
n_fich= 1;
fich{1}= 'glass.data'; % 文件路徑名

n_max= max(n_patrons);
x = zeros(n_fich, n_max, n_entradas); % 用於存放提取出的屬性數據
cl= zeros(n_fich, n_max);             % 用於存放數據標籤

n_patrons_total = sum(n_patrons); % 用於顯示進度
n_iter=0;

for i_fich=1:n_fich
    f=fopen(fich{i_fich}, 'r'); % 打開文件
    if -1==f
        error('打開數據文件出錯 %s\n', fich{i_fich});
    end
    
    for i=1:n_patrons(i_fich) % 循環對每行數據進行處理
        n_iter=n_iter+1;
        fprintf('%5.1f%%\r', 100*n_iter/n_patrons_total); % 顯示處理進度
        
        fscanf(f,'%i',1); % 第一個數字爲序號,無需記錄
        for j = 1:n_entradas
            temp=fscanf(f, ',%f',1); % 讀取下一個數據,以逗號分隔
            x(i_fich,i,j) = temp;    % 保存一個數值到x
        end
        t=fscanf(f,',%i',1);
        if t >= 5  % 原數據標記中沒有5,所以後面標號需要-1
            t = t - 1;
        end
        
        cl(i_fich,i) = t - 1;  	% 原標記從1開始,改爲從0開始
    end
    fclose(f);% 關閉文件
end


%% 處理完成,保存文件
fprintf('現在保存數據文件...\n')
data = squeeze(x); % 數據
label = cl';% 標籤
dataSet = [label,data];
dir_path=['./預處理完成/',data_name];
if exist('./預處理完成/','dir')==0   %該文件夾不存在,則直接創建
    mkdir('./預處理完成/');
end
saveData(dataSet,dir_path); % 保存文件至文件夾
fprintf('預處理完成\n')


%% 子函數,用於保存txt/data/mat三種類型文件
function saveData(DataSet,fileName)
% author:wuxian
% DataSet:整理好的數據集
% fileName:數據集的名字

%% Data爲整理好的數據集矩陣
mat_name = [fileName,'.mat'];
save(mat_name, 'DataSet')  % 保存.mat文件
data_name = [fileName,'.data'];
save(data_name,'DataSet','-ASCII'); % 保存data文件

% 保存txt文件
txt_name = [fileName,'.txt'];
f=fopen(txt_name,'w');
[m,n]=size(DataSet);
for i=1:m
    for j=1:n
        if j==n
            if i~=m
                fprintf(f,'%g \n',DataSet(i,j));
            else
                fprintf(f,'%g',DataSet(i,j));
            end
        else
            fprintf(f,'%g,',DataSet(i,j));
        end
    end
end
fclose(f);

% save iris.txt -ascii Iris
% dlmwrite('iris.txt',Iris);
end

  以上程序代碼的思路是提取每行中每個數據的屬性和標籤分別保存到與x, cl兩個矩陣中,然後通過調用子函數saveData( )保存數據爲txt, data, mat格式文件。數據提取的過程是通過遍歷每行數據,利用fscanf( )函數逐個讀取每個逗號分隔的數據,最後在第52行將得到的屬性和標籤合併成一個矩陣並將標籤放在第一列。運行程序後整理好的文件將保存在“預處理完成”的文件夾中,保存的文件及整理後的數據如下:

保存文件與整理好的數據
以上整理好的數據集第一列爲標籤(取值有0, 1, 2, 3, 4, 5),其餘列爲屬性並與原數據集一致。

2.2 “部分英文字符、無缺失”數據集

  相比前一小節中純數字的原始數據集,最爲常見的數據恐怕還是部分帶一些英文字符的了。有些數據集的某些特徵取值爲有限個數的離散值,例如Abalone數據集,從Abalone數據集下載頁下載該數據集,打開部分數據如下圖所示:

abalone數據集

  從上圖數據中可以看出只有第一列的屬性爲英文字符,其它屬性都是數字,根據Abalone數據集詳情頁上的介紹,該數據集的第一列屬性是鮑魚的性別,有雄性(M)、雌性(F)及幼期(I)三個取值,所以這裏需將第一個屬性中的英文字符“M, F, I”分別用數字“-1, 0, 1”代替。

  另外該數據集要預測的物理量是鮑魚的年齡,原始數據集年齡那一列數據(最後一列)實際爲連續取值,在該數據集的“屬性信息”中有介紹到該數據集既可以作爲連續值預測也可以用於分類任務。所以這裏在處理Abalone數據集的標籤時需要將連續數值離散化,我們可以根據鮑魚年齡age的取值分爲:“age<9,9<age<11,age>11age<9, 9<age<11, age>11”三類,分別用數字“-1, 0, 1”表示。這是針對這一單個數據集而言的,如果數據集標籤本身就是可以直接用於分類的,就無需進行離散化了。

  按照上面的分析,處理這種數據集時我們只需替換第一列英文字符並將最後一列的標籤離散化。在下載的數據文件存放路徑處新建Matlab\color{#4285f4}{M}\color{#ea4335}{a}\color{#fbbc05}{t}\color{#4285f4}{l}\color{#34a853}{a}\color{#ea4335}{b}程序,創建一個命名爲main.m的文件,並在編輯器鍵入如下代碼:

%% abalone
% author: wuxian, website: https://wuxian.blog.csdn.net
clear;
clc;
data_name = 'abalone';
fprintf(['處理數據集: ',data_name,'abalone 原始數據 ...\n']);
fich= [data_name,'.data'];

n_entradas= 8; % 屬性數
n_clases= 3;  % 分類數
n_fich= 1; % 數據集個數
n_patrons= 4177; % 數據量(行數)

x = zeros(n_patrons, n_entradas); % 用於存放提取出的屬性數據
cl= zeros(1, n_patrons);% 用於存放數據標籤

f=fopen(fich, 'r');% 打開文件
if -1==f
    error('打開文件出錯 %s\n', fich);
end
for i=1:n_patrons % 循環對每行數據進行處理
    
    fprintf('%5.1f%%\r', 100*i/n_patrons(1));% 顯示處理進度
    
    t = fscanf(f, '%c', 1); % 讀取一個字符數據
    switch t % 將對應字符替換爲數字
        case 'M'
            x(i,1)=-1;
        case 'F'
            x(i,1)=0;
        case 'I'
            x(i,1)=1;
    end
    
    for j=2:n_entradas
        fscanf(f,'%c',1); % 中間有分隔符,後移1個位置
        x(i,j) = fscanf(f,'%f', 1);% 依次讀取這一行所有屬性
    end
    
    fscanf(f,'%c',1); 
    t = fscanf(f,'%i', 1); % 讀取最後的標記值
    % 根據範圍將連續的標記值離散化爲三類
    if t < 9
        cl(1,i)=0;
    elseif t < 11
        cl(1,i)=1;
    else
        cl(1,i)=2;
    end
    fscanf(f,'%c',1);
    
end
fclose(f);

%% 處理完成,保存文件
fprintf('現在保存數據文件...\n')
data = x; % 數據
label = cl';% 標籤
dataSet = [label,data];
dir_path=['./預處理完成/',data_name];
if exist('./預處理完成/','dir')==0   %該文件夾不存在,則直接創建
    mkdir('./預處理完成/');
end
saveData(dataSet,dir_path); % 保存文件至文件夾
fprintf('預處理完成\n')


%% 子函數,用於保存txt/data/mat三種類型文件
function saveData(DataSet,fileName)
% DataSet:整理好的數據集
% fileName:數據集的名字

%% Data爲整理好的數據集矩陣
mat_name = [fileName,'.mat'];
save(mat_name, 'DataSet')  % 保存.mat文件
data_name = [fileName,'.data'];
save(data_name,'DataSet','-ASCII'); % 保存data文件

% 保存txt文件
txt_name = [fileName,'.txt'];
f=fopen(txt_name,'w');
[m,n]=size(DataSet);
for i=1:m
    for j=1:n
        if j==n
            if i~=m
                fprintf(f,'%g \n',DataSet(i,j));
            else
                fprintf(f,'%g',DataSet(i,j));
            end
        else
            fprintf(f,'%g,',DataSet(i,j));
        end
    end
end
fclose(f);

% save iris.txt -ascii Iris
% dlmwrite('iris.txt',Iris);
end

  和前面整理的思路類似,這裏還是使用x, cl兩個矩陣保存從原始文件中提取的屬性和標籤,其中讀取每個數值點採用循環調用fscanf( )函數逐個移動文件指針的方式讀取,將提取的數據屬性保存在x矩陣中。代碼第25-33行讀取出第一個屬性值並根據它的取值不同分別對x的第一個元素賦不同的數字。代碼第41-49行讀取最後一列數值,並根據其值的取值範圍將其劃分爲三個標籤值的其中一個。至於各數據點之間的逗號分割符,程序中使用fscanf( )函數移動指針到下一個數據位置而並未賦值到變量中,從而跳過了逗號分隔符,如代碼第36,40,50行。運行以上代碼,得到整理完成的數據文件及部分數據截圖如下:

整理後的abalone數據集
以上整理好的數據集第一列爲標籤(取值有0, 1, 2),其餘列爲屬性,第一個屬性已處理爲數字(取值有-1, 0, 1

2.3 “部分英文字符、有缺失”數據集

  經過前面兩個例子的介紹我們再來看一個更加複雜點的數據集類型即除了有英文字符還有缺失數據的部分。以Adult數據集爲例,這個數據集前面已多有介紹,改數據集有劃分好的訓練集和測試集,所以從AdultData Folder下載adult.dataadult.test兩個數據文件,部分數據如下圖:

adult數據集
  字符型離散值轉化爲數值型:我們可以將某個需要轉化爲數值型的字符型屬性的全部可能取值存放在一個元胞數組中並記取值個數爲nn,而轉化後的數值範圍一般取[1,1][-1, 1],所以我們在[1,1][-1, 1]的取值範圍內平均取nn個實數{1,3nn1,...,2k1nn1,...,n3n1,1},k=1,2,3,...,n1,n\{-1, \frac{3-n}{n-1}, ..., \frac{2k-1-n}{n-1}, ...,\frac{n-3}{n-1}, 1\}, k=1,2,3, ...,n-1, n用來代替這些字符型屬性。比方說Adult原始數據的第2個屬性表示工作類型有’Private’, ‘Self-emp-not-inc’, ‘Self-emp-inc’, ‘Federal-gov’, ‘Local-gov’, ‘State-gov’, ‘Without-pay’, 'Never-worked’將被分別替換爲數值1,57,37,17,17,37,57,1-1, -\frac{5}{7}, -\frac{3}{7}, -\frac{1}{7}, \frac{1}{7}, \frac{3}{7}, \frac{5}{7}, 1。在程序中比對字符串然後可按以上公式順序賦值爲相應的數值。

  缺失數據處理:對於缺失數據的處理其實現在並沒有一個很好的解決方式,一般來說缺失的數據點較少時可以直接刪去,較常見的是採用該屬性的均值、中值或衆數來填充缺失,當然也可以直接補充爲某些特定值。直接刪去數據會導致數據量減少,而均值填補主要用於連續資料的缺失,這裏的數據集屬性大多爲離散量,使用均值並不是一個很好的方法。以上方法大家可以分別嘗試一下,這裏直接對缺失的數據補充特定值0處理。

  在下載的數據文件存放路徑處新建Matlab\color{#4285f4}{M}\color{#ea4335}{a}\color{#fbbc05}{t}\color{#4285f4}{l}\color{#34a853}{a}\color{#ea4335}{b}程序,創建一個命名爲main.m的文件,並在編輯器鍵入如下代碼:

%% adult
% author:wx  website:https://wuxian.blog.csdn.net
clear;
clc;

data_name = 'adult';% 數據集名
fprintf('lendo problema adult...\n');

n_entradas= 14; % 屬性數
n_clases= 2; % 分類數
n_fich= 2; % 文件數,含有訓練和測試集
fich{1}= 'adult.data';% 訓練數據路徑
n_patrons(1)= 32561; % 訓練集數據量

fich{2}= 'adult.test'; % 測試數據路徑
n_patrons(2)= 16281;   % 測試數據量

n_max= max(n_patrons);
x = zeros(n_fich, n_max, n_entradas); % 屬性數據
cl= zeros(n_fich, n_max);             % 標籤

discreta = [0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1]; % 1表示該位置的屬性需要將字符型離散值轉化爲數值型

% 字符型離散值的所有取值
workclass = {'Private', 'Self-emp-not-inc', 'Self-emp-inc', 'Federal-gov', 'Local-gov', 'State-gov', 'Without-pay', 'Never-worked'};
education = {'Bachelors', 'Some-college', '11th', 'HS-grad', 'Prof-school', 'Assoc-acdm', 'Assoc-voc', '9th', '7th-8th', '12th', 'Masters', '1st-4th', '10th', 'Doctorate', '5th-6th', 'Preschool'};
marital = {'Married-civ-spouse', 'Divorced', 'Never-married', 'Separated', 'Widowed', 'Married-spouse-absent', 'Married-AF-spouse'};
occupation = {'Tech-support', 'Craft-repair', 'Other-service', 'Sales', 'Exec-managerial', 'Prof-specialty', 'Handlers-cleaners', 'Machine-op-inspct', 'Adm-clerical', 'Farming-fishing', 'Transport-moving', 'Priv-house-serv', 'Protective-serv', 'Armed-Forces'};
relationship = {'Wife', 'Own-child', 'Husband', 'Not-in-family', 'Other-relative', 'Unmarried'};
race = {'White', 'Asian-Pac-Islander', 'Amer-Indian-Eskimo', 'Other', 'Black'};
sex = {'Male', 'Female'};
country = {'United-States', 'Cambodia', 'England', 'Puerto-Rico', 'Canada', 'Germany', 'Outlying-US(Guam-USVI-etc)', 'India', 'Japan', 'Greece', 'South', 'China', 'Cuba', 'Iran', 'Honduras', 'Philippines', 'Italy', 'Poland', 'Jamaica', 'Vietnam', 'Mexico', 'Portugal', 'Ireland', 'France', 'Dominican-Republic', 'Laos', 'Ecuador', 'Taiwan', 'Haiti', 'Columbia', 'Hungary', 'Guatemala', 'Nicaragua', 'Scotland', 'Thailand', 'Yugoslavia', 'El-Salvador', 'Trinadad&Tobago', 'Peru', 'Hong', 'Holand-Netherlands'};

% 字符型離散值的所有取值個數
n_workclass=8; 
n_education=16; 
n_marital=7; 
n_occupation=14; 
n_relationship=6; 
n_race=5; 
n_sex=2; 
n_country=41;

for i_fich = 1:n_fich
    f=fopen(fich{i_fich}, 'r');
    if -1==f
        error('打開數據文件出錯 %s\n', fich{i_fich});
    end
    
    for i=1:n_patrons(i_fich)
        fprintf('%5.1f%%\r', 100*i/n_patrons(i_fich)); % 顯示進度
        
        for j = 1:n_entradas
            if discreta(j)==1
                s = fscanf(f,'%s',1); 
                s = s(1:end-1); % 去掉字符串末尾的逗號
                if strcmp(s, '?')  % 對於缺失值補0
                    x(i_fich,i,j)=0;
                else
                    % 確定具體的屬性位置並賦相應變量
                    if j==2
                        n = n_workclass; p=workclass;
                    elseif j==4
                        n = n_education; p=education;
                    elseif j==6
                        n = n_marital; p=marital;
                    elseif j==7
                        n = n_occupation; p=occupation;
                    elseif j==8
                        n = n_relationship; p=relationship;
                    elseif j==9
                        n = n_race; p=race;
                    elseif j==10
                        n = n_sex; p=sex;
                    elseif j==14
                        n = n_country; p=country;
                    end
                    % 根據讀取的字符值按排列順序轉化爲-11之間的分數值
                    a = 2/(n-1); b= (1+n)/(1-n);
                    for k=1:n
                        if strcmp(s, p(k))
                            x(i_fich,i,j) = a*k + b; 
                            break
                        end
                    end
                end
            else %0的位置(原數據就是數值型)直接讀取原數據
                temp = fscanf(f,'%g',1); 
                x(i_fich,i,j) = temp; 
                fscanf(f,'%c',1);
            end

        end
        
        s = fscanf(f,'%s',1);
        % 將標籤轉化爲數值型(0,1if strcmp(s, '<=50K')||strcmp(s, '<=50K.')
            cl(i_fich,i)=0;
        elseif strcmp(s, '>50K')||strcmp(s, '>50K.')
            cl(i_fich,i)=1;
        else
            error('類別標籤 %s 讀取出錯\n', s)
        end

    end
    fclose(f);
end


%% 處理完成,保存文件
fprintf('現在保存數據文件...\n')
dir_path=['./預處理完成/',data_name];
if exist('./預處理完成/','dir')==0   %該文件夾不存在,則直接創建
    mkdir('./預處理完成/');
end
data_train =  squeeze(x(1,1:n_patrons(1),:)); % 數據
label_train = squeeze(cl(1,1:n_patrons(1)))';% 標籤
dataSet_train = [label_train, data_train];
saveData(dataSet_train,[dir_path,'_train']); % 保存文件至文件夾

data_test =  squeeze(x(2,1:n_patrons(2),:)); % 數據
label_test = squeeze(cl(2,1:n_patrons(2)))';% 標籤
dataSet_test = [label_test,data_test];
saveData(dataSet_test,[dir_path,'_test']);

fprintf('預處理完成\n')


%% 子函數,用於保存txt/data/mat三種類型文件
function saveData(DataSet,fileName)
% DataSet:整理好的數據集
% fileName:數據集的名字

%% Data爲整理好的數據集矩陣
mat_name = [fileName,'.mat'];
save(mat_name, 'DataSet')  % 保存.mat文件
data_name = [fileName,'.data'];
save(data_name,'DataSet','-ASCII'); % 保存data文件

% 保存txt文件
txt_name = [fileName,'.txt'];
f=fopen(txt_name,'w');
[m,n]=size(DataSet);
for i=1:m
    for j=1:n
        if j==n
            if i~=m
                fprintf(f,'%g \n',DataSet(i,j));
            else
                fprintf(f,'%g',DataSet(i,j));
            end
        else
            fprintf(f,'%g,',DataSet(i,j));
        end
    end
end
fclose(f);

% save iris.txt -ascii Iris
% dlmwrite('iris.txt',Iris);
end

  這裏代碼在前面一個的基礎上做了改進,對於原文件屬性是數值型的直接讀取到x矩陣中,對於字符型的屬性按照順序對應爲[-1, 1]上的離散數值。運行以上代碼,得到整理完成的數據文件及部分數據截圖如下:

整理後的adult數據集
以上整理好的數據集第一列爲標籤(取值有0, 1),其餘列爲屬性,其中的字符型屬性已處理爲數值型。

  至此不同數據集的整理程序就介紹到這裏了,UCI\color{#4285f4}{U}\color{#ea4335}{C}\color{#fbbc05}{I}\color{#4285f4}數據集數量衆多,雖然沒有統一的整理代碼但經過這三個例子大家可以參考修改整理自己需要的數據集了。如果您有更好的整理方法歡迎在下方留言哦。


3. 148個整理好的數據集與對應程序

  博主在三年的機器學習學習和研究中已累計整理了148個論文和研究中常用的UCI數據集,後面還會繼續整理更多數據集並更新下載資源。查找、下載和整理數據集是件費時費力的事情,完整整理好足夠論文或研究學習中需要的數據集可能會花費好多天甚至數週的時間,爲了減少重複整理數據的繁冗工作,這裏博主將自己整理好的148UCI數據集分享給大家,其中每個文件夾中都包含了以下內容:

  1. 從官網下載的完整原始數據文件
  2. 整理數據集、歸一化及劃分訓練測試數據集的完整Matlab\color{#4285f4}{M}\color{#ea4335}{a}\color{#fbbc05}{t}\color{#4285f4}{l}\color{#34a853}{a}\color{#ea4335}{b}程序文件
  3. 整理完成後的數據集文件

您可以直接使用裏面整理好的數據集文件,也可以修改或重新運行整理的程序代碼,整理好的148UCI數據集截圖如下:

整理好的全部文件目錄
文件中的所有程序代碼均在Matlab\color{#4285f4}{M}\color{#ea4335}{a}\color{#fbbc05}{t}\color{#4285f4}{l}\color{#34a853}{a}\color{#ea4335}{b} R2016b中測試運行通過,整理的好數據集也是經過檢查和自行使用過的,每個子文件夾裏面的文件內容截圖如下,下面提供了下載鏈接歡迎前去下載。

文件夾詳情圖

【資源獲取】
  若您想獲得博文中介紹的整理Glass數據集、Abalone數據集及Adult數據集涉及的完整程序文件(包含三個數據的原始文件、整理數據集程序代碼文件及整理好的文件)掃描以下二維碼並關注公衆號“AI技術研究與分享”,後臺回覆“UC20200223”獲取。
公衆號二維碼

148個整理好的UCI數據集下載】

  爲大家提供優質的資源是博主一直堅持的動力,若您想獲得上述介紹的148個整理好的UCI數據集,可以點擊如下鏈接到博主的麪包多網頁上下載,麪包多網站可以直接點擊解鎖,完成後可解鎖頁面下方的下載鏈接圖標,點擊即可下載。

下載鏈接:博主在麪包多網站上的完整資源下載頁


結束語

  由於博主能力有限,博文中提及的方法即使經過試驗,也難免會有疏漏之處。希望您能熱心指出其中的錯誤,以便下次修改時能以一個更完美更嚴謹的樣子,呈現在大家面前。同時如果有更好的實現方法也請您不吝賜教。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章