-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
K 결정 및 알고리즘 성능 판단(실루엣 이용) 함수 추가, 테스트 #33
Changes from 12 commits
d736dfa
2befd87
77c841b
b583cff
4c92afe
08a69e9
66bc2c9
16f540c
45d38f7
5eeea79
8f87891
dab1d33
7497d63
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// | ||
// KCoefficient.swift | ||
// InteractiveClusteringMap | ||
// | ||
// Created by A on 2020/11/25. | ||
// | ||
|
||
import Foundation | ||
|
||
// rule of thumb | ||
func KwithRuleOfThumb(numberOfData: Int) -> Int { | ||
return Int(sqrt(Double(numberOfData/2))) | ||
} | ||
|
||
// AverageSilhouetteMethod | ||
class AverageSilhouetteCalculator { | ||
|
||
private let clusters: [Cluster] | ||
|
||
init(clusters: [Cluster]) { | ||
self.clusters = clusters | ||
} | ||
|
||
func findAverageSilhouette(cluster: Cluster) -> Double { | ||
var silhouettes = [Double]() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 띄어쓰기가 두번이.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 린트에서 오류가 뜨진 않았나요? |
||
cluster.coordinates.forEach { coordinate in | ||
silhouettes.append(findSilhouette(with: cluster, target: coordinate)) | ||
} | ||
return silhouettes.reduce(.zero, +) / Double(silhouettes.count) | ||
} | ||
|
||
func findSilhouette(with cluster: Cluster, target: Coordinate) -> Double { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기두 계산아닌가용..? |
||
guard !cluster.coordinates.isEmpty else { | ||
return 0.0 | ||
} | ||
let cohesion = findCohesion(in: cluster, target: target) | ||
let separation = findSeparation(in: cluster, target: target) | ||
return (separation - cohesion) / max(cohesion, separation) | ||
} | ||
|
||
// 점과 현재 포함된 클러스터의 응집도 계산 | ||
func findCohesion(in cluster: Cluster, target: Coordinate) -> Double { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 응집도 계산이라서 find 보다 calculate 이런게 나아보여요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 클래스 명이 계산기니까 calculate가 더 나아 보이네요!! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그냥 cohesion 도 괜찮을거 같구용 ! |
||
var totalDistance = 0.0 | ||
let coordinates = cluster.coordinates.filter { $0 != target } | ||
coordinates.forEach { | ||
totalDistance += target.distanceTo($0) | ||
} | ||
return totalDistance / Double(coordinates.count) | ||
} | ||
|
||
// 점과 포함되지 않은 클러스터 간의 분리도 계산 | ||
func findSeparation(in cluster: Cluster, target: Coordinate) -> Double { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기두 calculate가 나을거같은데 아니면 말씀해주세용! |
||
var totalDistances: [Double] = [Double]() | ||
let otherClusters = clusters.filter { $0.coordinates != cluster.coordinates } | ||
otherClusters.forEach { | ||
totalDistances.append(findCohesion(in: $0, target: target)) | ||
} | ||
return totalDistances.min() ?? 0 | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,9 +40,36 @@ extension BoundingBox: Equatable {} | |
|
||
struct Coordinate: Equatable { | ||
|
||
static let zero = Coordinate(x: 0, y: 0) | ||
|
||
let x: Double | ||
let y: Double | ||
|
||
func distanceTo(_ other: Coordinate) -> Double { | ||
let powX = pow(self.x - other.x, 2.0) | ||
let powY = pow(self.y - other.y, 2.0) | ||
|
||
return sqrt(powX + powY) | ||
} | ||
|
||
static func + (left: Coordinate, right: Coordinate) -> Coordinate { | ||
let x = left.x + right.x | ||
let y = left.y + right.y | ||
return Coordinate(x: x, y: y) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기 개행 통일하면 보기 더 예쁠(?) 것 같아용 ㅎㅎ |
||
|
||
static func - (left: Coordinate, right: Coordinate) -> Coordinate { | ||
let x = left.x - right.x | ||
let y = left.y - right.y | ||
return Coordinate(x: x, y: y) | ||
} | ||
|
||
static func / (left: Coordinate, right: Double) -> Coordinate { | ||
let x = left.x / right | ||
let y = left.y / right | ||
return Coordinate(x: x, y: y) | ||
} | ||
|
||
static func <= (left: Coordinate, right: Coordinate) -> Bool { | ||
left.x <= right.x && left.y <= right.y | ||
} | ||
|
@@ -56,6 +83,11 @@ struct Coordinate: Equatable { | |
} | ||
|
||
struct Cluster { | ||
let center: Coordinate | ||
let coordinates: [Coordinate] | ||
var coordinates: [Coordinate] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 얘( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 여기는 팀원들이랑 논의하다가 뒤에 var로 바꿀일이 있어서 저도 바꿔놓았는데 사실상 이번 PR에서의 의미는 없네요 😅 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아아, 논의하신거라면 패쓰~ |
||
var center: Coordinate { | ||
coordinates.reduce(.zero, +) / Double(coordinates.count) | ||
} | ||
init(coordinates: [Coordinate]) { | ||
self.coordinates = coordinates | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
// | ||
// KDefineTests.swift | ||
// InteractiveClusteringMapTests | ||
// | ||
// Created by A on 2020/11/25. | ||
// | ||
|
||
import XCTest | ||
|
||
class KDefineTests: XCTestCase { | ||
|
||
let accuracy = 0.001 | ||
private var avc: AverageSilhouetteCalculator? | ||
|
||
/// cluster1: A(1,1), B(2,2) | ||
/// cluster2: C(-2,1), D(-3,-2), D(0, -2) | ||
private let cluster1 = Cluster(coordinates: [Coordinate(x: 1, y: 1), Coordinate(x: 2, y: 2)]) | ||
private var cluster2 = Cluster(coordinates: [Coordinate(x: -2, y: 1), Coordinate(x: -3, y: -2), Coordinate(x: 0, y: -2)]) | ||
|
||
override func setUpWithError() throws { | ||
let clusters = [cluster1, cluster2] | ||
avc = AverageSilhouetteCalculator(clusters: clusters) | ||
} | ||
|
||
func test_avc_init() throws { | ||
XCTAssertNotNil(avc) | ||
} | ||
|
||
func test_rule_of_thumb_with_5000() throws { | ||
let expected = 50 | ||
let numberOfData = 5000 | ||
XCTAssertEqual(KwithRuleOfThumb(numberOfData: numberOfData), expected) | ||
} | ||
|
||
func test_rule_of_thumb_with_8000() throws { | ||
let expected = 63 | ||
let numberOfData = 8000 | ||
XCTAssertEqual(KwithRuleOfThumb(numberOfData: numberOfData), expected) | ||
} | ||
|
||
func test_find_find_cohesion() throws { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. test_find_cohesion() ...? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 엥 이상한 이름들이 많네요 큐ㅠㅠ 바로 수정하겠습니다! |
||
guard let result = avc?.findCohesion(in: cluster1, target: cluster1.coordinates[0]) else { | ||
return | ||
} | ||
let expected = sqrt(2) | ||
XCTAssertEqual(expected, result, accuracy: accuracy) | ||
} | ||
|
||
func test_find_separation() throws { | ||
guard let result = avc?.findSeparation(in: cluster1, target: cluster1.coordinates[0]) else { | ||
return | ||
} | ||
|
||
let expected = 3.720759 | ||
XCTAssertEqual(expected, result, accuracy: accuracy) | ||
} | ||
|
||
func test_find_silhouette_A() throws { | ||
guard let result = avc?.findSilhouette(with: cluster1, target: cluster1.coordinates[0]) else { | ||
return | ||
} | ||
|
||
let expected = 0.619912 | ||
XCTAssertEqual(expected, result, accuracy: accuracy) | ||
} | ||
|
||
func test_find_silhouette_B() throws { | ||
guard let result = avc?.findSilhouette(with: cluster1, target: cluster1.coordinates[1]) else { | ||
return | ||
} | ||
|
||
let expected = 0.717126 | ||
XCTAssertEqual(expected, result, accuracy: accuracy) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 두 테스트 함수의 차이는 무엇인가요??? 같은 행동을 한다면 하나의 함수에서 하는건 어떤가요? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 테스트 함수당 xctAssert 함수가 하나씩 들어가는 게 이상적이라고 생각해서 나눴습니다!! |
||
|
||
func test_find_average_silhouette_cluster1() throws { | ||
guard let result = avc?.findAverageSilhouette(cluster: cluster1) else { | ||
return | ||
} | ||
|
||
let expected = 0.668519 | ||
XCTAssertEqual(expected, result, accuracy: accuracy) | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이거 return 생략 가능한거 어떻게 맞추면 좋을지 논의해보면 좋을 거 같애용 ㅎ_ㅎ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return 이 생략가능하다는게 어떤 의미인지 좀 더 설명해 주실 수 있나요!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이렇게용 ! 함수내부에 반환만하면 return 생략 가능하지 않나요 ~~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아 오오 이런 방법이 있는 줄은 몰랐네요! 생략을 하는게 더 나을까요 ? ? 논의 해봅시당 ㅎㅎ