2013-11-25 69 views
0

我正在做一個比較各種分類算法的有效性的項目,但我陷入了一個令人沮喪的地步。數據可能在這裏找到:http://archive.ics.uci.edu/ml/datasets/Adult分類問題是一個人根據他們的人口普查數據是否每年超過50k。計算混合特徵分類的向量距離

兩個例子分錄如下:

45,私人,98092,HS-畢業,9,已婚,CIV配偶,銷售,丈夫,白人,男性,0,0,60,美國,美國,< = 50K

50,Self-emp-not-inc,386397,Bachelors,13,已婚夫婦配偶,銷售,丈夫,白人,男性,0,0,60,美國,< = 50K

我熟悉使用歐幾里得距離來計算向量之間的差異,但我不確定如何使用連續屬性和離散屬性的混合。有沒有用有意義的方式表示兩個向量之間差異的有效方法?我很難理解像第三個屬性(由基於因素提取數據集的人計算的權重,以便相似的權重應該具有相似的屬性)以及它們之間的差異可以保持意義從男性或女性等離散特徵,如果我正確理解該方法,這只是歐幾里得距離爲1。我相信某些類別可能會被刪除,但我不想將這些因素明顯排除在分類之外。一旦我弄清楚了這一點,我首先要處理k-NN,然後是貝葉斯分類器,如果我有時間的話,最後是C4.5或ID3這樣的決策樹模型。

回答

1

當然,你可以用任何方法擴展歐氏距離。最簡單的擴展是以下規則:在協調,如果有一個匹配

距離= 0,否則爲1

的挑戰將是使距離「相關」的理念,爲K-NN跟進。在某些情況下(如教育),我認爲最好將教育(離散變量)映射爲連續變量,如教育年限。所以你需要編寫一個函數來映射例如「HS-grad」爲12,「Bachelors」爲16,類似的。

除此之外,直接使用k-NN不會起作用,因爲多個不相似的維度之間的「距離」的概念沒有很好的定義。我認爲你會更好地拋棄這些維度或者以不同的方式加權。我不知道數據集中的第三個數字(例如98092)是什麼意思,但是如果使用樸素歐幾里得距離,那麼與其他維度(如年齡)相比,這將極度超標。

我不是一個機器學習專家,但我個人會試圖在簡化的維度數據集上啓動k-NN,您只需選擇一些廣泛的人口統計數據(例如年齡,教育程度,婚姻狀況)並忽略更復雜/ 「嘈雜」類別。

+0

是的,我肯定會考慮扔掉那個類別,因爲你注意到的第三個數字的問題與我所做的是一樣的。我只是想知道是否有辦法將它或其他類別轉化爲有意義但不具有過度影響力的價值。我曾考慮過縮小尺寸,但我可能不得不試驗一下,看哪些是有意義的,哪些不是。 – Baldier

+0

對此的+1:「直接使用k-NN不會工作,因爲多個不相似的維度之間的」距離「的想法沒有明確定義」:) – bendaizer

0

您需要將您的分類變量編碼爲1的n個二進制變量(變量的n個選項,以及這些變量中只有一個是活動的)。然後標準化你的特徵---對於每個特徵,減去其均值和除以標準差。或者規範化到0-1的範圍。這並不完美,但這至少會使尺寸具有可比性。

+0

我沒有聽說過標準偏差過程,我一定會看看這個。謝謝。 – Baldier

0

爲每個數據點創建單獨的地圖並使用地圖轉換爲雙倍值。

def createMap(data: RDD[String]) : Map[String,Double] = { 
var mapData:Map[String,Double] = Map() 
var counter = 0.0 
data.collect().foreach{ item => 
    counter = counter +1 
    mapData += (item -> counter) 
} 
mapData 
} 

def getLablelValue(input: String): Int = input match { 
case "<=50K" => 0 
case ">50K" => 1 
} 


val census = sc.textFile("/user/cloudera/census_data.txt") 
val orgTypeRdd = census.map(line => line.split(", ")(1)).distinct 
val gradeTypeRdd = census.map(line => line.split(", ")(3)).distinct 
val marStatusRdd = census.map(line => line.split(", ")(5)).distinct 
val jobTypeRdd = census.map(line => line.split(", ")(6)).distinct 
val familyStatusRdd = census.map(line => line.split(", ")(7)).distinct 
val raceTypeRdd = census.map(line => line.split(", ")(8)).distinct 
val genderTypeRdd = census.map(line => line.split(", ")(9)).distinct 
val countryRdd = census.map(line => line.split(", ")(13)).distinct 
val salaryRange = census.map(line => line.split(", ")(14)).distinct 

val orgTypeMap = createMap(orgTypeRdd) 
val gradeTypeMap = createMap(gradeTypeRdd) 
val marStatusMap = createMap(marStatusRdd) 
val jobTypeMap = createMap(jobTypeRdd) 
val familyStatusMap = createMap(familyStatusRdd) 
val raceTypeMap = createMap(raceTypeRdd) 
val genderTypeMap = createMap(genderTypeRdd) 
val countryMap = createMap(countryRdd) 
val salaryRangeMap = createMap(salaryRange) 


val featureVector = census.map{line => 
    val fields = line.split(", ") 
LabeledPoint(getLablelValue(fields(14).toString) , Vectors.dense(fields(0).toDouble, orgTypeMap(fields(1).toString) , fields(2).toDouble , gradeTypeMap(fields(3).toString) , fields(4).toDouble , marStatusMap(fields(5).toString), jobTypeMap(fields(6).toString), familyStatusMap(fields(7).toString),raceTypeMap(fields(8).toString),genderTypeMap (fields(9).toString), fields(10).toDouble , fields(11).toDouble , fields(12).toDouble,countryMap(fields(13).toString) , salaryRangeMap(fields(14).toString))) 
}