spark 빌딩 - 결정 트 리 분류 기 -- spark. mlib
12687 단어 기술 층 - spark
방법 소개
의사 결정 트 리 (decision tree) 는 기본 적 인 분류 와 회귀 방법 으로 분류 에 사용 되 는 의사 결정 트 리 를 소개 한다.결정 트 리 모델 은 트 리 구 조 를 나타 내 는데 그 중에서 모든 내부 노드 는 하나의 속성 상의 테스트 를 나타 내 고 모든 가 지 는 하나의 테스트 출력 을 대표 하 며 모든 잎 노드 는 하나의 유형 을 대표 한다.학습 시 훈련 데 이 터 를 이용 하여 손실 함수 최소 화 원칙 에 따라 결정 트 리 모델 을 구축한다.예측 할 때 새로운 데 이 터 를 결정 트 리 모델 로 분류 한다.
2. 기본 원리
결정 트 리 학습 은 보통 세 가지 절 차 를 포함한다. 특징 선택, 결정 트 리 의 생 성과 결정 트 리 의 가지치기 이다.
(1) 특징 선택
특징 선택 은 훈련 데이터 에 대해 분류 능력 을 가 진 특징 을 선택 하면 결정 트 리 학습 의 효율 을 높 일 수 있다.일반적인 특징 선택의 준칙 은 정보 이득 (또는 정보 이득 비, 지 니 지수 등) 으로 매번 각 특징의 정보 이득 을 계산 하고 그들의 크기 를 비교 하 며 정보 이득 이 가장 크다 (정보 이득 비 최대, 지 니 지수 최소) 는 특징 을 선택한다.다음은 특징 선택의 준칙 인 정보 이득 을 중점적으로 소개 한다.
먼저 정보 론 에서 광범 위 하 게 사용 되 는 도량 기준 인 엔트로피 (entropy) 를 정의 합 니 다. 이것 은 무 작위 변수의 불확실 성 을 나타 내 는 도량 입 니 다.엔트로피 가 클 수록 무 작위 변수의 불확실 성 이 커진다.한편, 정보 이득 (informational entropy) 은 특정한 특징 을 알 게 된 후에 정보의 불확실 성 을 감소 시 키 는 정 도 를 나타 낸다.쉽게 말 하면 하나의 속성의 정보 이득 은 바로 이 속성 분할 사례 를 사용 하여 기대 엔트로피 가 낮 아 지 는 것 이다.정보 이득, 정보 이득 비 와 지 니 지수의 구체 적 인 정 의 는 다음 과 같다.
정보 이득: 특징 A 가 훈련 데이터 세트 D 에 대한 정보 이득 g (D, A) g (D, A) g (D, A), 집합 D 의 경험 엔트로피 H (D) H (D) H (D) H (D)) 와 특징 A 가 주어진 조건 에서 D 의 경험 조건 엔트로피 H (D | A) H (D | A) 의 차, 즉 g (D, A) = H (D) - H (D | A) g (D, A) = H (D) - H (D) - H (D | A) 정보 이득 비: 특징 A 가 훈련 데이터 세트 D 에 대한 정보 이득 비 gR (D, A) gR (D, A) gR (D, A, A) 를 정보 이득 g (D, A) g (D, A) g (D, A) g (D, A) g (D, A) g (D, A A)특징 A 의 값 에 대한 훈련 데이터 세트 D 의 엔트로피 HA (D) HA (D) 에 비해 gR (D, A) = g (D, A) HA (D, A) gR (D) = g (D, A) HA (D)
그 중에서 HA (D) = − ∑ ni = 1 | Di | D | log 2 | D | HA (D) = − ∑ i = 1n | Di | D | log 2 | Di | | D |, n 은 특징 A 의 값 을 추출 하 는 개수 이다.
지 니 지수: 분류 문제 에서 K 종류 가 있다 고 가정 하면 샘플 점 이 K 종류 에 속 할 확률 은 pkpkpk 이 고 확률 분포 의 지 니 지 수 는 다음 과 같이 정의 된다.
Gini(p)=K∑k=1pk(1−pk)=1−K∑k=1p2kGini(p)=∑k=1Kpk(1−pk)=1−∑k=1Kpk2
(2) 의사 결정 트 리 의 생 성
뿌리 결점 부터 결점 에 대해 가능 한 모든 특징의 정보 이득 을 계산 하고 정보 이득 의 가장 큰 특징 을 결점 의 특징 으로 선택 하여 이 특징의 서로 다른 수치 로 서브 결점 을 만 든 다음 에 서브 결점 에 대해 상기 방법 을 재 귀적 으로 호출 하여 결정 트 리 를 구축한다.모든 특징의 정보 가 작 거나 특징 이 없 을 때 까지 마지막 으로 결정 트 리 를 얻 을 수 있다.
결정 트 리 는 성장 을 중지 하 는 정지 조건 이 있어 야 한다.일반적으로 가장 낮은 조건 은 이 노드 아래 의 모든 기록 이 같은 종류 에 속 하거나 모든 기록 속성 이 같은 값 을 가 질 때 이다.이 두 가지 조건 은 의사 결정 트 리 를 중단 하 는 필수 조건 이자 가장 낮은 조건 이다.실제 운용 에서 일반적으로 결정 트 리 가 성장 을 미리 멈 추고 잎 노드 에 포 함 된 최저 데 이 터 량 을 한정 하여 과도 한 성장 으로 인 한 과도 한 의합 문 제 를 방지 하 기 를 바란다.
(3) 결정 트 리 의 가지치기
결정 트 리 생 성 알고리즘 은 계속 할 수 없 을 때 까지 재 귀적 으로 결정 트 리 를 만 듭 니 다.이렇게 생 긴 나 무 는 훈련 데이터 에 대한 분류 가 정확 하지만 알 수 없 는 테스트 데이터 에 대한 분 류 는 그다지 정확 하지 않다. 즉, 적합 현상 이 나타 난 적 이 있다.이 문 제 를 해결 하 는 방법 은 결정 트 리 의 복잡 도 를 고려 하여 이미 생 성 된 결정 트 리 를 간소화 하 는 것 이다. 이 과정 을 가지치기 라 고 한다.
결정 트 리 의 가 지 는 결정 트 리 의 전체적인 손실 함 수 를 극소 화 함으로써 이 루어 진다.일반적으로 손실 함 수 는 다음 과 같은 정 의 를 내 릴 수 있다. Ca (T) = C (T) + a | T | Ca (T) = C (T) + a | T | 그 중에서 T 는 임 의 서브 트 리 이 고 C (T) C (T) 는 훈련 데이터 에 대한 예측 오차 (예 를 들 어 지 니 지수), | T | T | 는 서브 트 리 의 잎 결점 개수 이 며 a ≥ 0a ≥ 0 은 매개 변수 이 며 Ca (T) Ca (T) 는 매개 변수 가 aa 시의 서브 트 리 T 의 전체적인 손실 이다.매개 변수 aa 는 훈련 데이터 의 적합 도와 모델 의 복잡 도 를 저울질 한다.고정된 aa 에 대해 서 는 손실 함수 Ca (T) Ca (T) 를 최소 화 하 는 하위 트 리 가 반드시 존재 하 며 이 를 Tata 라 고 표시 합 니 다.aa 가 클 때 가장 좋 은 나무 인 Tata 는 작 습 니 다.aa 가 어 렸 을 때 가장 좋 은 나무 인 Tata 는 비교적 컸 다.
3. 예시 코드
저 희 는 iris 데이터 세트 로 (https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data) 예 를 들 어 분석한다.아이 리 스 는 아이 리 스 의 특징 을 데이터 소스 로 하고 데이터 세트 는 150 개의 데이터 세트 를 포함 하 며 3 가지 로 나 뉘 는데 각각 50 개의 데 이 터 를 포함 하고 모든 데 이 터 는 4 개의 속성 을 포함 하 며 데이터 발굴, 데이터 분류 에서 매우 자주 사용 되 는 테스트 세트, 훈련 세트 이다.
1. 필요 한 가방 가 져 오기:
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.mllib.tree.DecisionTree
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.linalg.{Vectors,Vector}
2. 데이터 읽 기:
우선, 텍스트 파일 읽 기;그리고 맵 을 통 해 각 줄 의 데 이 터 를 "," 분리 해서 우리 의 데이터 에 집중 하면 각 줄 은 5 부분 으로 나 뉘 는데 앞의 4 부분 은 붓꽃 의 4 가지 특징 이 고 마지막 부분 은 붓꽃 의 분류 이다.라벨 열 과 특징 열 을 LabeledPoint 로 저장 합 니 다.LabeledPoint 는 감독 학습 에서 라벨 과 특징 을 저장 하 는 데 자주 사용 되 는데 그 중에서 라벨 의 유형 은 double 이 고 특징 적 인 유형 은 Vector 입 니 다.그래서 우 리 는 꾀꼬리 꽃의 분 류 를 바 꾸 었 다. 'Iris - setosa' 는 0, 'Iris - versicolor' 는 1, 나머지 는 2 로 분류 했다.그리고 꾀꼬리 꽃의 네 가지 특징 을 가 져 와 Vector 에 저장 합 니 다.
scala> val data = sc.textFile("G:/spark/iris.data")
data: org.apache.spark.rdd.RDD[String] = G:/spark/iris.data MapPartitionsRDD[1]
at textFile at :26
scala> val parsedData = data.map { line =>
| val parts = line.split(',')
| LabeledPoint(if(parts(4)=="Iris-setosa") 0.toDouble else if (parts(4)
=="Iris-versicolor") 1.toDouble else
| 2.toDouble, Vectors.dense(parts(0).toDouble,parts(1).toDouble,parts
(2).toDouble,parts(3).toDouble))
| }
parsedData: org.apache.spark.rdd.RDD[org.apache.spark.mllib.regression.LabeledPo
int] = MapPartitionsRDD[2] at map at :28
그리고 우 리 는 데 이 터 를 인쇄 해서 보 자.
scala> parsedData.foreach { x => println(x) }
(0.0,[5.1,3.5,1.4,0.2])
(1.0,[6.0,2.9,4.5,1.5])
(0.0,[4.9,3.0,1.4,0.2])
(1.0,[5.7,2.6,3.5,1.0])
(0.0,[4.7,3.2,1.3,0.2])
... ...
3. 모델 구축
그 다음 에 먼저 데이터 세트 를 구분 하고 여기 서 70% 의 훈련 집 과 30% 의 테스트 집 을 나눈다.
scala> val splits = parsedData.randomSplit(Array(0.7, 0.3))
splits: Array[org.apache.spark.rdd.RDD[org.apache.spark.mllib.regression.Labeled
Point]] = Array(MapPartitionsRDD[3] at randomSplit at :30, MapPartition
sRDD[4] at randomSplit at :30)
scala> val (trainingData, testData) = (splits(0), splits(1))
trainingData: org.apache.spark.rdd.RDD[org.apache.spark.mllib.regression.Labeled
Point] = MapPartitionsRDD[3] at randomSplit at :30
testData: org.apache.spark.rdd.RDD[org.apache.spark.mllib.regression.LabeledPoin
t] = MapPartitionsRDD[4] at randomSplit at :30
그 다음 에 결정 트 리 의 trainClassifier 방법 으로 결정 트 리 모델 을 구축 하고 파 라 메 터 를 설정 합 니 다. 예 를 들 어 분류 수, 정보 이득 의 선택, 나무의 최대 깊이 등 입 니 다.
scala> val numClasses = 3
numClasses: Int = 3
scala> val categoricalFeaturesInfo = Map[Int, Int]()
categoricalFeaturesInfo: scala.collection.immutable.Map[Int,Int] = Map()
scala> val impurity = "gini"
impurity: String = gini
scala> val maxDepth = 5
maxDepth: Int = 5
scala> val maxBins = 32
maxBins: Int = 32
scala> val model = DecisionTree.trainClassifier(trainingData, numClasses, categoricalFeaturesInfo, impurity, maxDepth, maxBins)
model: org.apache.spark.mllib.tree.model.DecisionTreeModel = DecisionTreeModel c
lassifier of depth 5 with 15 nodes
그 다음 에 우 리 는 결정 트 리 모델 의 predict 방법 을 호출 하여 테스트 데이터 세트 를 예측 하고 모델 구 조 를 인쇄 합 니 다.
scala> val labelAndPreds = testData.map { point =>
| val prediction = model.predict(point.features)
| (point.label, prediction)
| }
labelAndPreds: org.apache.spark.rdd.RDD[(Double, Double)] = MapPartitionsRDD[28]
at map at :40
scala> println("Learned classification tree model:
" + model.toDebugString)
Learned classification tree model:
DecisionTreeModel classifier of depth 5 with 15 nodes
If (feature 2 <= 1.9)
Predict: 0.0
Else (feature 2 > 1.9)
If (feature 2 <= 4.8)
If (feature 3 <= 1.6)
Predict: 1.0
Else (feature 3 > 1.6)
If (feature 1 <= 2.8)
Predict: 2.0
Else (feature 1 > 2.8)
Predict: 1.0
Else (feature 2 > 4.8)
If (feature 3 <= 1.7)
If (feature 2 <= 5.1)
If (feature 3 <= 1.5)
Predict: 2.0
Else (feature 3 > 1.5)
Predict: 1.0
Else (feature 2 > 5.1)
Predict: 2.0
Else (feature 3 > 1.7)
Predict: 2.0
4. 모델 평가
마지막 으로 우 리 는 모델 예측 의 정확성 을 인쇄 했다.
scala> val testErr = labelAndPreds.filter(r => r._1 != r._2).count().toDouble / testData.count()
testErr: Double = 0.05128205128205128
scala> println("Precision = " + (1-testErr))
Precision = 0.9487179487179487