2013-11-25 72 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))) 
}