Расчет векторного расстояния для классификации со смешанными объектами

Я делаю проект, сравнивающий эффективность различных алгоритмов классификации, но застрял на одном неприятном моменте. Данные можно найти здесь: http://archive.ics.uci.edu/ml/datasets/Adult Проблема классификации заключается в том, зарабатывает ли человек более 50 тысяч в год на основе данных переписи населения.

Вот два примера записей:

45, рядовой, 98092, выпускник HS, 9, женат, гражданский супруг, продавец, муж, белый, мужской, 0, 0, 60, США, ‹= 50K

50, Self-emp-not-inc, 386397, холостяк, 13 лет, женат, гражданский супруг, продавец, муж, белый, мужской, 0, 0, 60, США, ‹= 50K

Я знаком с использованием евклидова расстояния для вычисления разницы между векторами, но не знаю, как работать с сочетанием непрерывных и дискретных атрибутов. Существуют ли какие-либо эффективные методы значимого представления разницы между двумя векторами? Мне трудно понять, насколько большие значения, такие как третий атрибут (вес, рассчитанный людьми, которые извлекли набор данных на основе факторов, так что одинаковые веса должны иметь похожие атрибуты), и различия между ним могут сохранять значение от дискретных черт, таких как мужчина или женщина, что составляет только евклидово расстояние, равное 1, если я правильно понимаю метод. Я уверен, что некоторые категории можно удалить, но я не хочу удалять то, что существенно влияет на классификацию. Сначала я обращаюсь к k-NN, как только я это выясню, затем к байесовскому классификатору и, наконец, к модели дерева решений, такой как C4.5 или ID3, если у меня есть время.


person Baldier    schedule 25.11.2013    source источник


Ответы (3)


Конечно, вы можете увеличить евклидово расстояние любым количеством способов. Самым простым расширением было бы следующее правило:

distance = 0 в этой координате, если есть совпадение, 1 в противном случае

Задача будет заключаться в том, чтобы сделать концепцию расстояния «актуальной» для продолжения k-NN. В некоторых случаях (например, образование), я думаю, будет лучше отобразить образование (дискретную переменную) в непрерывную переменную, такую ​​как годы обучения. Поэтому вам нужно написать функцию, которая отображает, например, «HS-град» до 12, «Холостяк» до 16, что-то в этом роде.

Кроме того, использование k-NN напрямую не сработает, потому что идея «расстояния» между несколькими несходными измерениями четко не определена. Думаю, вам лучше отбросить некоторые из этих измерений или по-другому взвесить их. Я не знаю, что означает третье число в вашем наборе данных (например, 98092), но если вы будете использовать наивное евклидово расстояние, оно будет чрезвычайно завышенным по сравнению с другими измерениями, такими как возраст.

Я не эксперт по машинному обучению, но лично мне хотелось бы начать k-NN на наборе данных с уменьшенной размерностью, где вы просто выбираете некоторые широкие демографические данные (например, возраст, образование, семейное положение) и игнорируете более сложные / «шумные» категории. .

person wandering star    schedule 25.11.2013
comment
Да, я определенно подумал о том, чтобы выбросить эту категорию, потому что проблема, которую вы заметили с третьим числом, та же самая, что и я. Мне просто было интересно, есть ли способ превратить это или другие категории в значимую, но не слишком значимую ценность. Я подумал об уменьшении размеров, но мне, вероятно, придется поэкспериментировать, чтобы увидеть, какие из них значимы, а какие нет. - person Baldier; 26.11.2013
comment
+1 для этого: использование k-NN напрямую не сработает, потому что идея расстояния между несколькими разнородными измерениями не очень хорошо определена :) - person bendaizer; 26.11.2013

Вам необходимо закодировать категориальные переменные как двоичные переменные 1 из n (n вариантов для переменной, и из этих переменных активна только одна). Затем стандартизируйте свои функции --- для каждой функции вычтите ее среднее значение и разделите на стандартное отклонение. Или нормализовать в диапазоне 0-1. Он не идеален, но, по крайней мере, сравним по размерам.

person Ben Allison    schedule 26.11.2013
comment
Я не слышал о процессе стандартного отклонения, я обязательно взгляну на него. Спасибо. - person Baldier; 26.11.2013

Создайте отдельные карты для каждой точки данных и используйте карту для преобразования в двойное значение.

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)))
}
person Charls Joseph    schedule 21.07.2016