├── .gitignore ├── KRKmeans.podspec ├── KRKmeans.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── KRKmeans.xccheckout │ └── xcuserdata │ │ └── Kalvar.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── Kalvar.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── KRKmeans.xcscheme │ └── xcschememanagement.plist ├── KRKmeans ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ └── Main.storyboard ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── KRKmeans-Info.plist ├── KRKmeans-Prefix.pch ├── ViewController.h ├── ViewController.m ├── en.lproj │ └── InfoPlist.strings └── main.m ├── KRKmeansTests ├── KRKmeansTests-Info.plist ├── KRKmeansTests.m └── en.lproj │ └── InfoPlist.strings ├── LICENSE ├── ML ├── KRKmeans.h ├── KRKmeans.m ├── KRKmeansGroup │ ├── KRKmeansCenter │ │ ├── KRKmeansCenter.h │ │ └── KRKmeansCenter.m │ ├── KRKmeansGroup.h │ ├── KRKmeansGroup.m │ └── KRKmeansPattern │ │ ├── KRKmeansPattern.h │ │ └── KRKmeansPattern.m ├── KRKmeansKernel │ ├── KRKmeansKernel.h │ └── KRKmeansKernel.m ├── KRKmeansOne │ ├── KRKmeansOne.h │ ├── KRKmeansOne.m │ └── NSArray+Statistics.h └── KRKmeansSaver │ ├── KRKmeansSaver.h │ └── KRKmeansSaver.m └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # CocoaPods 2 | # 3 | # We recommend against adding the Pods directory to your .gitignore. However 4 | # you should judge for yourself, the pros and cons are mentioned at: 5 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control? 6 | # 7 | # Pods/ 8 | 9 | -------------------------------------------------------------------------------- /KRKmeans.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "KRKmeans" 3 | s.version = "2.6.1" 4 | s.summary = "KRKmeans is clustering algorithm (クラスタリング分類) that one of Machine Learning methods." 5 | s.description = <<-DESC 6 | KRKmeans has implemented K-Means the clustering algorithm (クラスタリング分類) and achieved multi-dimensional clustering in this project. KRKmeans could be used in data mining (データマイニング), image compression (画像圧縮) and classification. 7 | DESC 8 | s.homepage = "https://github.com/Kalvar/ios-KRKmeans-Algorithm" 9 | s.license = { :type => 'MIT', :file => 'LICENSE' } 10 | s.author = { "Kalvar Lin" => "ilovekalvar@gmail.com" } 11 | s.social_media_url = "https://twitter.com/ilovekalvar" 12 | s.source = { :git => "https://github.com/Kalvar/ios-KRKmeans-Algorithm.git", :tag => s.version.to_s } 13 | s.platform = :ios, '7.0' 14 | s.requires_arc = true 15 | s.public_header_files = 'ML/**/*.h' 16 | s.source_files = 'ML/**/*.{h,m}' 17 | s.frameworks = 'Foundation' 18 | end -------------------------------------------------------------------------------- /KRKmeans.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8E3F30E91BF850EE004FEC88 /* KRKmeans.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E3F30E01BF850EE004FEC88 /* KRKmeans.m */; }; 11 | 8E3F30EA1BF850EE004FEC88 /* KRKmeansOne.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E3F30E31BF850EE004FEC88 /* KRKmeansOne.m */; }; 12 | 8EA7282F1D02C4D1007F4EA9 /* KRKmeansKernel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EA7282E1D02C4D1007F4EA9 /* KRKmeansKernel.m */; }; 13 | 8EA728321D02D58B007F4EA9 /* KRKmeansGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EA728311D02D58B007F4EA9 /* KRKmeansGroup.m */; }; 14 | 8EA7283A1D02D635007F4EA9 /* KRKmeansPattern.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EA728391D02D635007F4EA9 /* KRKmeansPattern.m */; }; 15 | 8EA7283D1D02D657007F4EA9 /* KRKmeansCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EA7283C1D02D657007F4EA9 /* KRKmeansCenter.m */; }; 16 | 8EA7284A1D09A16D007F4EA9 /* KRKmeansSaver.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EA728491D09A16D007F4EA9 /* KRKmeansSaver.m */; }; 17 | 8EE975321960257200335EB2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8EE975311960257200335EB2 /* Foundation.framework */; }; 18 | 8EE975341960257200335EB2 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8EE975331960257200335EB2 /* CoreGraphics.framework */; }; 19 | 8EE975361960257200335EB2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8EE975351960257200335EB2 /* UIKit.framework */; }; 20 | 8EE9753C1960257200335EB2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8EE9753A1960257200335EB2 /* InfoPlist.strings */; }; 21 | 8EE9753E1960257200335EB2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EE9753D1960257200335EB2 /* main.m */; }; 22 | 8EE975421960257200335EB2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EE975411960257200335EB2 /* AppDelegate.m */; }; 23 | 8EE975451960257200335EB2 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8EE975431960257200335EB2 /* Main.storyboard */; }; 24 | 8EE975481960257200335EB2 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EE975471960257200335EB2 /* ViewController.m */; }; 25 | 8EE9754A1960257200335EB2 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8EE975491960257200335EB2 /* Images.xcassets */; }; 26 | 8EE975511960257200335EB2 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8EE975501960257200335EB2 /* XCTest.framework */; }; 27 | 8EE975521960257200335EB2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8EE975311960257200335EB2 /* Foundation.framework */; }; 28 | 8EE975531960257200335EB2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8EE975351960257200335EB2 /* UIKit.framework */; }; 29 | 8EE9755B1960257200335EB2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8EE975591960257200335EB2 /* InfoPlist.strings */; }; 30 | 8EE9755D1960257200335EB2 /* KRKmeansTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EE9755C1960257200335EB2 /* KRKmeansTests.m */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXContainerItemProxy section */ 34 | 8EE975541960257200335EB2 /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = 8EE975261960257100335EB2 /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = 8EE9752D1960257200335EB2; 39 | remoteInfo = KRKmeans; 40 | }; 41 | /* End PBXContainerItemProxy section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | 8E3F30DF1BF850EE004FEC88 /* KRKmeans.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRKmeans.h; sourceTree = ""; }; 45 | 8E3F30E01BF850EE004FEC88 /* KRKmeans.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KRKmeans.m; sourceTree = ""; }; 46 | 8E3F30E21BF850EE004FEC88 /* KRKmeansOne.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRKmeansOne.h; sourceTree = ""; }; 47 | 8E3F30E31BF850EE004FEC88 /* KRKmeansOne.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KRKmeansOne.m; sourceTree = ""; }; 48 | 8EA7282D1D02C4D1007F4EA9 /* KRKmeansKernel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRKmeansKernel.h; sourceTree = ""; }; 49 | 8EA7282E1D02C4D1007F4EA9 /* KRKmeansKernel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KRKmeansKernel.m; sourceTree = ""; }; 50 | 8EA728301D02D58B007F4EA9 /* KRKmeansGroup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRKmeansGroup.h; sourceTree = ""; }; 51 | 8EA728311D02D58B007F4EA9 /* KRKmeansGroup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KRKmeansGroup.m; sourceTree = ""; }; 52 | 8EA728381D02D635007F4EA9 /* KRKmeansPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRKmeansPattern.h; sourceTree = ""; }; 53 | 8EA728391D02D635007F4EA9 /* KRKmeansPattern.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KRKmeansPattern.m; sourceTree = ""; }; 54 | 8EA7283B1D02D657007F4EA9 /* KRKmeansCenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRKmeansCenter.h; sourceTree = ""; }; 55 | 8EA7283C1D02D657007F4EA9 /* KRKmeansCenter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KRKmeansCenter.m; sourceTree = ""; }; 56 | 8EA7283E1D02DD4E007F4EA9 /* NSArray+Statistics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSArray+Statistics.h"; sourceTree = ""; }; 57 | 8EA728481D09A16D007F4EA9 /* KRKmeansSaver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRKmeansSaver.h; sourceTree = ""; }; 58 | 8EA728491D09A16D007F4EA9 /* KRKmeansSaver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KRKmeansSaver.m; sourceTree = ""; }; 59 | 8EE9752E1960257200335EB2 /* KRKmeans.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KRKmeans.app; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | 8EE975311960257200335EB2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 61 | 8EE975331960257200335EB2 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 62 | 8EE975351960257200335EB2 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 63 | 8EE975391960257200335EB2 /* KRKmeans-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KRKmeans-Info.plist"; sourceTree = ""; }; 64 | 8EE9753B1960257200335EB2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 65 | 8EE9753D1960257200335EB2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 66 | 8EE9753F1960257200335EB2 /* KRKmeans-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "KRKmeans-Prefix.pch"; sourceTree = ""; }; 67 | 8EE975401960257200335EB2 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 68 | 8EE975411960257200335EB2 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 69 | 8EE975441960257200335EB2 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 70 | 8EE975461960257200335EB2 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 71 | 8EE975471960257200335EB2 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 72 | 8EE975491960257200335EB2 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 73 | 8EE9754F1960257200335EB2 /* KRKmeansTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KRKmeansTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 74 | 8EE975501960257200335EB2 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 75 | 8EE975581960257200335EB2 /* KRKmeansTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "KRKmeansTests-Info.plist"; sourceTree = ""; }; 76 | 8EE9755A1960257200335EB2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 77 | 8EE9755C1960257200335EB2 /* KRKmeansTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KRKmeansTests.m; sourceTree = ""; }; 78 | /* End PBXFileReference section */ 79 | 80 | /* Begin PBXFrameworksBuildPhase section */ 81 | 8EE9752B1960257200335EB2 /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | 8EE975341960257200335EB2 /* CoreGraphics.framework in Frameworks */, 86 | 8EE975361960257200335EB2 /* UIKit.framework in Frameworks */, 87 | 8EE975321960257200335EB2 /* Foundation.framework in Frameworks */, 88 | ); 89 | runOnlyForDeploymentPostprocessing = 0; 90 | }; 91 | 8EE9754C1960257200335EB2 /* Frameworks */ = { 92 | isa = PBXFrameworksBuildPhase; 93 | buildActionMask = 2147483647; 94 | files = ( 95 | 8EE975511960257200335EB2 /* XCTest.framework in Frameworks */, 96 | 8EE975531960257200335EB2 /* UIKit.framework in Frameworks */, 97 | 8EE975521960257200335EB2 /* Foundation.framework in Frameworks */, 98 | ); 99 | runOnlyForDeploymentPostprocessing = 0; 100 | }; 101 | /* End PBXFrameworksBuildPhase section */ 102 | 103 | /* Begin PBXGroup section */ 104 | 8E3F30DE1BF850EE004FEC88 /* ML */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 8E3F30DF1BF850EE004FEC88 /* KRKmeans.h */, 108 | 8E3F30E01BF850EE004FEC88 /* KRKmeans.m */, 109 | 8EA7282B1D02C4BD007F4EA9 /* KRKmeansGroup */, 110 | 8EA7282C1D02C4BD007F4EA9 /* KRKmeansKernel */, 111 | 8E3F30E11BF850EE004FEC88 /* KRKmeansOne */, 112 | 8EA728471D09A16D007F4EA9 /* KRKmeansSaver */, 113 | ); 114 | path = ML; 115 | sourceTree = ""; 116 | }; 117 | 8E3F30E11BF850EE004FEC88 /* KRKmeansOne */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 8EA7283E1D02DD4E007F4EA9 /* NSArray+Statistics.h */, 121 | 8E3F30E21BF850EE004FEC88 /* KRKmeansOne.h */, 122 | 8E3F30E31BF850EE004FEC88 /* KRKmeansOne.m */, 123 | ); 124 | path = KRKmeansOne; 125 | sourceTree = ""; 126 | }; 127 | 8EA7282B1D02C4BD007F4EA9 /* KRKmeansGroup */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 8EA728371D02D635007F4EA9 /* KRKmeansPattern */, 131 | 8EA728361D02D635007F4EA9 /* KRKmeansCenter */, 132 | 8EA728301D02D58B007F4EA9 /* KRKmeansGroup.h */, 133 | 8EA728311D02D58B007F4EA9 /* KRKmeansGroup.m */, 134 | ); 135 | path = KRKmeansGroup; 136 | sourceTree = ""; 137 | }; 138 | 8EA7282C1D02C4BD007F4EA9 /* KRKmeansKernel */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | 8EA7282D1D02C4D1007F4EA9 /* KRKmeansKernel.h */, 142 | 8EA7282E1D02C4D1007F4EA9 /* KRKmeansKernel.m */, 143 | ); 144 | path = KRKmeansKernel; 145 | sourceTree = ""; 146 | }; 147 | 8EA728361D02D635007F4EA9 /* KRKmeansCenter */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 8EA7283B1D02D657007F4EA9 /* KRKmeansCenter.h */, 151 | 8EA7283C1D02D657007F4EA9 /* KRKmeansCenter.m */, 152 | ); 153 | path = KRKmeansCenter; 154 | sourceTree = ""; 155 | }; 156 | 8EA728371D02D635007F4EA9 /* KRKmeansPattern */ = { 157 | isa = PBXGroup; 158 | children = ( 159 | 8EA728381D02D635007F4EA9 /* KRKmeansPattern.h */, 160 | 8EA728391D02D635007F4EA9 /* KRKmeansPattern.m */, 161 | ); 162 | path = KRKmeansPattern; 163 | sourceTree = ""; 164 | }; 165 | 8EA728471D09A16D007F4EA9 /* KRKmeansSaver */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 8EA728481D09A16D007F4EA9 /* KRKmeansSaver.h */, 169 | 8EA728491D09A16D007F4EA9 /* KRKmeansSaver.m */, 170 | ); 171 | path = KRKmeansSaver; 172 | sourceTree = ""; 173 | }; 174 | 8EE975251960257100335EB2 = { 175 | isa = PBXGroup; 176 | children = ( 177 | 8E3F30DE1BF850EE004FEC88 /* ML */, 178 | 8EE975371960257200335EB2 /* KRKmeans */, 179 | 8EE975381960257200335EB2 /* Supporting Files */, 180 | 8EE975561960257200335EB2 /* KRKmeansTests */, 181 | 8EE975301960257200335EB2 /* Frameworks */, 182 | 8EE9752F1960257200335EB2 /* Products */, 183 | ); 184 | sourceTree = ""; 185 | }; 186 | 8EE9752F1960257200335EB2 /* Products */ = { 187 | isa = PBXGroup; 188 | children = ( 189 | 8EE9752E1960257200335EB2 /* KRKmeans.app */, 190 | 8EE9754F1960257200335EB2 /* KRKmeansTests.xctest */, 191 | ); 192 | name = Products; 193 | sourceTree = ""; 194 | }; 195 | 8EE975301960257200335EB2 /* Frameworks */ = { 196 | isa = PBXGroup; 197 | children = ( 198 | 8EE975311960257200335EB2 /* Foundation.framework */, 199 | 8EE975331960257200335EB2 /* CoreGraphics.framework */, 200 | 8EE975351960257200335EB2 /* UIKit.framework */, 201 | 8EE975501960257200335EB2 /* XCTest.framework */, 202 | ); 203 | name = Frameworks; 204 | sourceTree = ""; 205 | }; 206 | 8EE975371960257200335EB2 /* KRKmeans */ = { 207 | isa = PBXGroup; 208 | children = ( 209 | 8EE975401960257200335EB2 /* AppDelegate.h */, 210 | 8EE975411960257200335EB2 /* AppDelegate.m */, 211 | 8EE975431960257200335EB2 /* Main.storyboard */, 212 | 8EE975461960257200335EB2 /* ViewController.h */, 213 | 8EE975471960257200335EB2 /* ViewController.m */, 214 | 8EE975491960257200335EB2 /* Images.xcassets */, 215 | ); 216 | path = KRKmeans; 217 | sourceTree = ""; 218 | }; 219 | 8EE975381960257200335EB2 /* Supporting Files */ = { 220 | isa = PBXGroup; 221 | children = ( 222 | 8EE975391960257200335EB2 /* KRKmeans-Info.plist */, 223 | 8EE9753A1960257200335EB2 /* InfoPlist.strings */, 224 | 8EE9753D1960257200335EB2 /* main.m */, 225 | 8EE9753F1960257200335EB2 /* KRKmeans-Prefix.pch */, 226 | ); 227 | name = "Supporting Files"; 228 | path = KRKmeans; 229 | sourceTree = ""; 230 | }; 231 | 8EE975561960257200335EB2 /* KRKmeansTests */ = { 232 | isa = PBXGroup; 233 | children = ( 234 | 8EE9755C1960257200335EB2 /* KRKmeansTests.m */, 235 | 8EE975571960257200335EB2 /* Supporting Files */, 236 | ); 237 | path = KRKmeansTests; 238 | sourceTree = ""; 239 | }; 240 | 8EE975571960257200335EB2 /* Supporting Files */ = { 241 | isa = PBXGroup; 242 | children = ( 243 | 8EE975581960257200335EB2 /* KRKmeansTests-Info.plist */, 244 | 8EE975591960257200335EB2 /* InfoPlist.strings */, 245 | ); 246 | name = "Supporting Files"; 247 | sourceTree = ""; 248 | }; 249 | /* End PBXGroup section */ 250 | 251 | /* Begin PBXNativeTarget section */ 252 | 8EE9752D1960257200335EB2 /* KRKmeans */ = { 253 | isa = PBXNativeTarget; 254 | buildConfigurationList = 8EE975601960257200335EB2 /* Build configuration list for PBXNativeTarget "KRKmeans" */; 255 | buildPhases = ( 256 | 8EE9752A1960257200335EB2 /* Sources */, 257 | 8EE9752B1960257200335EB2 /* Frameworks */, 258 | 8EE9752C1960257200335EB2 /* Resources */, 259 | ); 260 | buildRules = ( 261 | ); 262 | dependencies = ( 263 | ); 264 | name = KRKmeans; 265 | productName = KRKmeans; 266 | productReference = 8EE9752E1960257200335EB2 /* KRKmeans.app */; 267 | productType = "com.apple.product-type.application"; 268 | }; 269 | 8EE9754E1960257200335EB2 /* KRKmeansTests */ = { 270 | isa = PBXNativeTarget; 271 | buildConfigurationList = 8EE975631960257200335EB2 /* Build configuration list for PBXNativeTarget "KRKmeansTests" */; 272 | buildPhases = ( 273 | 8EE9754B1960257200335EB2 /* Sources */, 274 | 8EE9754C1960257200335EB2 /* Frameworks */, 275 | 8EE9754D1960257200335EB2 /* Resources */, 276 | ); 277 | buildRules = ( 278 | ); 279 | dependencies = ( 280 | 8EE975551960257200335EB2 /* PBXTargetDependency */, 281 | ); 282 | name = KRKmeansTests; 283 | productName = KRKmeansTests; 284 | productReference = 8EE9754F1960257200335EB2 /* KRKmeansTests.xctest */; 285 | productType = "com.apple.product-type.bundle.unit-test"; 286 | }; 287 | /* End PBXNativeTarget section */ 288 | 289 | /* Begin PBXProject section */ 290 | 8EE975261960257100335EB2 /* Project object */ = { 291 | isa = PBXProject; 292 | attributes = { 293 | LastUpgradeCheck = 0700; 294 | ORGANIZATIONNAME = Kalvar; 295 | TargetAttributes = { 296 | 8EE9754E1960257200335EB2 = { 297 | TestTargetID = 8EE9752D1960257200335EB2; 298 | }; 299 | }; 300 | }; 301 | buildConfigurationList = 8EE975291960257100335EB2 /* Build configuration list for PBXProject "KRKmeans" */; 302 | compatibilityVersion = "Xcode 3.2"; 303 | developmentRegion = English; 304 | hasScannedForEncodings = 0; 305 | knownRegions = ( 306 | en, 307 | Base, 308 | ); 309 | mainGroup = 8EE975251960257100335EB2; 310 | productRefGroup = 8EE9752F1960257200335EB2 /* Products */; 311 | projectDirPath = ""; 312 | projectRoot = ""; 313 | targets = ( 314 | 8EE9752D1960257200335EB2 /* KRKmeans */, 315 | 8EE9754E1960257200335EB2 /* KRKmeansTests */, 316 | ); 317 | }; 318 | /* End PBXProject section */ 319 | 320 | /* Begin PBXResourcesBuildPhase section */ 321 | 8EE9752C1960257200335EB2 /* Resources */ = { 322 | isa = PBXResourcesBuildPhase; 323 | buildActionMask = 2147483647; 324 | files = ( 325 | 8EE9754A1960257200335EB2 /* Images.xcassets in Resources */, 326 | 8EE9753C1960257200335EB2 /* InfoPlist.strings in Resources */, 327 | 8EE975451960257200335EB2 /* Main.storyboard in Resources */, 328 | ); 329 | runOnlyForDeploymentPostprocessing = 0; 330 | }; 331 | 8EE9754D1960257200335EB2 /* Resources */ = { 332 | isa = PBXResourcesBuildPhase; 333 | buildActionMask = 2147483647; 334 | files = ( 335 | 8EE9755B1960257200335EB2 /* InfoPlist.strings in Resources */, 336 | ); 337 | runOnlyForDeploymentPostprocessing = 0; 338 | }; 339 | /* End PBXResourcesBuildPhase section */ 340 | 341 | /* Begin PBXSourcesBuildPhase section */ 342 | 8EE9752A1960257200335EB2 /* Sources */ = { 343 | isa = PBXSourcesBuildPhase; 344 | buildActionMask = 2147483647; 345 | files = ( 346 | 8EA7283A1D02D635007F4EA9 /* KRKmeansPattern.m in Sources */, 347 | 8EA7284A1D09A16D007F4EA9 /* KRKmeansSaver.m in Sources */, 348 | 8EE975481960257200335EB2 /* ViewController.m in Sources */, 349 | 8E3F30E91BF850EE004FEC88 /* KRKmeans.m in Sources */, 350 | 8EE975421960257200335EB2 /* AppDelegate.m in Sources */, 351 | 8EA7283D1D02D657007F4EA9 /* KRKmeansCenter.m in Sources */, 352 | 8EA728321D02D58B007F4EA9 /* KRKmeansGroup.m in Sources */, 353 | 8EA7282F1D02C4D1007F4EA9 /* KRKmeansKernel.m in Sources */, 354 | 8E3F30EA1BF850EE004FEC88 /* KRKmeansOne.m in Sources */, 355 | 8EE9753E1960257200335EB2 /* main.m in Sources */, 356 | ); 357 | runOnlyForDeploymentPostprocessing = 0; 358 | }; 359 | 8EE9754B1960257200335EB2 /* Sources */ = { 360 | isa = PBXSourcesBuildPhase; 361 | buildActionMask = 2147483647; 362 | files = ( 363 | 8EE9755D1960257200335EB2 /* KRKmeansTests.m in Sources */, 364 | ); 365 | runOnlyForDeploymentPostprocessing = 0; 366 | }; 367 | /* End PBXSourcesBuildPhase section */ 368 | 369 | /* Begin PBXTargetDependency section */ 370 | 8EE975551960257200335EB2 /* PBXTargetDependency */ = { 371 | isa = PBXTargetDependency; 372 | target = 8EE9752D1960257200335EB2 /* KRKmeans */; 373 | targetProxy = 8EE975541960257200335EB2 /* PBXContainerItemProxy */; 374 | }; 375 | /* End PBXTargetDependency section */ 376 | 377 | /* Begin PBXVariantGroup section */ 378 | 8EE9753A1960257200335EB2 /* InfoPlist.strings */ = { 379 | isa = PBXVariantGroup; 380 | children = ( 381 | 8EE9753B1960257200335EB2 /* en */, 382 | ); 383 | name = InfoPlist.strings; 384 | sourceTree = ""; 385 | }; 386 | 8EE975431960257200335EB2 /* Main.storyboard */ = { 387 | isa = PBXVariantGroup; 388 | children = ( 389 | 8EE975441960257200335EB2 /* Base */, 390 | ); 391 | name = Main.storyboard; 392 | sourceTree = ""; 393 | }; 394 | 8EE975591960257200335EB2 /* InfoPlist.strings */ = { 395 | isa = PBXVariantGroup; 396 | children = ( 397 | 8EE9755A1960257200335EB2 /* en */, 398 | ); 399 | name = InfoPlist.strings; 400 | sourceTree = ""; 401 | }; 402 | /* End PBXVariantGroup section */ 403 | 404 | /* Begin XCBuildConfiguration section */ 405 | 8EE9755E1960257200335EB2 /* Debug */ = { 406 | isa = XCBuildConfiguration; 407 | buildSettings = { 408 | ALWAYS_SEARCH_USER_PATHS = NO; 409 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 410 | CLANG_CXX_LIBRARY = "libc++"; 411 | CLANG_ENABLE_MODULES = YES; 412 | CLANG_ENABLE_OBJC_ARC = YES; 413 | CLANG_WARN_BOOL_CONVERSION = YES; 414 | CLANG_WARN_CONSTANT_CONVERSION = YES; 415 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 416 | CLANG_WARN_EMPTY_BODY = YES; 417 | CLANG_WARN_ENUM_CONVERSION = YES; 418 | CLANG_WARN_INT_CONVERSION = YES; 419 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 420 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 421 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 422 | COPY_PHASE_STRIP = NO; 423 | ENABLE_TESTABILITY = YES; 424 | GCC_C_LANGUAGE_STANDARD = gnu99; 425 | GCC_DYNAMIC_NO_PIC = NO; 426 | GCC_OPTIMIZATION_LEVEL = 0; 427 | GCC_PREPROCESSOR_DEFINITIONS = ( 428 | "DEBUG=1", 429 | "$(inherited)", 430 | ); 431 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 432 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 433 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 434 | GCC_WARN_UNDECLARED_SELECTOR = YES; 435 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 436 | GCC_WARN_UNUSED_FUNCTION = YES; 437 | GCC_WARN_UNUSED_VARIABLE = YES; 438 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 439 | ONLY_ACTIVE_ARCH = YES; 440 | SDKROOT = iphoneos; 441 | }; 442 | name = Debug; 443 | }; 444 | 8EE9755F1960257200335EB2 /* Release */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | ALWAYS_SEARCH_USER_PATHS = NO; 448 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 449 | CLANG_CXX_LIBRARY = "libc++"; 450 | CLANG_ENABLE_MODULES = YES; 451 | CLANG_ENABLE_OBJC_ARC = YES; 452 | CLANG_WARN_BOOL_CONVERSION = YES; 453 | CLANG_WARN_CONSTANT_CONVERSION = YES; 454 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 455 | CLANG_WARN_EMPTY_BODY = YES; 456 | CLANG_WARN_ENUM_CONVERSION = YES; 457 | CLANG_WARN_INT_CONVERSION = YES; 458 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 459 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 460 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 461 | COPY_PHASE_STRIP = YES; 462 | ENABLE_NS_ASSERTIONS = NO; 463 | GCC_C_LANGUAGE_STANDARD = gnu99; 464 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 465 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 466 | GCC_WARN_UNDECLARED_SELECTOR = YES; 467 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 468 | GCC_WARN_UNUSED_FUNCTION = YES; 469 | GCC_WARN_UNUSED_VARIABLE = YES; 470 | IPHONEOS_DEPLOYMENT_TARGET = 7.1; 471 | SDKROOT = iphoneos; 472 | VALIDATE_PRODUCT = YES; 473 | }; 474 | name = Release; 475 | }; 476 | 8EE975611960257200335EB2 /* Debug */ = { 477 | isa = XCBuildConfiguration; 478 | buildSettings = { 479 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 480 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 481 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 482 | GCC_PREFIX_HEADER = "KRKmeans/KRKmeans-Prefix.pch"; 483 | INFOPLIST_FILE = "KRKmeans/KRKmeans-Info.plist"; 484 | PRODUCT_BUNDLE_IDENTIFIER = "com.kalvar.kmeans.${PRODUCT_NAME:rfc1034identifier}"; 485 | PRODUCT_NAME = "$(TARGET_NAME)"; 486 | WRAPPER_EXTENSION = app; 487 | }; 488 | name = Debug; 489 | }; 490 | 8EE975621960257200335EB2 /* Release */ = { 491 | isa = XCBuildConfiguration; 492 | buildSettings = { 493 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 494 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 495 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 496 | GCC_PREFIX_HEADER = "KRKmeans/KRKmeans-Prefix.pch"; 497 | INFOPLIST_FILE = "KRKmeans/KRKmeans-Info.plist"; 498 | PRODUCT_BUNDLE_IDENTIFIER = "com.kalvar.kmeans.${PRODUCT_NAME:rfc1034identifier}"; 499 | PRODUCT_NAME = "$(TARGET_NAME)"; 500 | WRAPPER_EXTENSION = app; 501 | }; 502 | name = Release; 503 | }; 504 | 8EE975641960257200335EB2 /* Debug */ = { 505 | isa = XCBuildConfiguration; 506 | buildSettings = { 507 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/KRKmeans.app/KRKmeans"; 508 | FRAMEWORK_SEARCH_PATHS = ( 509 | "$(SDKROOT)/Developer/Library/Frameworks", 510 | "$(inherited)", 511 | "$(DEVELOPER_FRAMEWORKS_DIR)", 512 | ); 513 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 514 | GCC_PREFIX_HEADER = "KRKmeans/KRKmeans-Prefix.pch"; 515 | GCC_PREPROCESSOR_DEFINITIONS = ( 516 | "DEBUG=1", 517 | "$(inherited)", 518 | ); 519 | INFOPLIST_FILE = "KRKmeansTests/KRKmeansTests-Info.plist"; 520 | PRODUCT_BUNDLE_IDENTIFIER = "com.kalvar.kmeans.${PRODUCT_NAME:rfc1034identifier}"; 521 | PRODUCT_NAME = "$(TARGET_NAME)"; 522 | TEST_HOST = "$(BUNDLE_LOADER)"; 523 | WRAPPER_EXTENSION = xctest; 524 | }; 525 | name = Debug; 526 | }; 527 | 8EE975651960257200335EB2 /* Release */ = { 528 | isa = XCBuildConfiguration; 529 | buildSettings = { 530 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/KRKmeans.app/KRKmeans"; 531 | FRAMEWORK_SEARCH_PATHS = ( 532 | "$(SDKROOT)/Developer/Library/Frameworks", 533 | "$(inherited)", 534 | "$(DEVELOPER_FRAMEWORKS_DIR)", 535 | ); 536 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 537 | GCC_PREFIX_HEADER = "KRKmeans/KRKmeans-Prefix.pch"; 538 | INFOPLIST_FILE = "KRKmeansTests/KRKmeansTests-Info.plist"; 539 | PRODUCT_BUNDLE_IDENTIFIER = "com.kalvar.kmeans.${PRODUCT_NAME:rfc1034identifier}"; 540 | PRODUCT_NAME = "$(TARGET_NAME)"; 541 | TEST_HOST = "$(BUNDLE_LOADER)"; 542 | WRAPPER_EXTENSION = xctest; 543 | }; 544 | name = Release; 545 | }; 546 | /* End XCBuildConfiguration section */ 547 | 548 | /* Begin XCConfigurationList section */ 549 | 8EE975291960257100335EB2 /* Build configuration list for PBXProject "KRKmeans" */ = { 550 | isa = XCConfigurationList; 551 | buildConfigurations = ( 552 | 8EE9755E1960257200335EB2 /* Debug */, 553 | 8EE9755F1960257200335EB2 /* Release */, 554 | ); 555 | defaultConfigurationIsVisible = 0; 556 | defaultConfigurationName = Release; 557 | }; 558 | 8EE975601960257200335EB2 /* Build configuration list for PBXNativeTarget "KRKmeans" */ = { 559 | isa = XCConfigurationList; 560 | buildConfigurations = ( 561 | 8EE975611960257200335EB2 /* Debug */, 562 | 8EE975621960257200335EB2 /* Release */, 563 | ); 564 | defaultConfigurationIsVisible = 0; 565 | defaultConfigurationName = Release; 566 | }; 567 | 8EE975631960257200335EB2 /* Build configuration list for PBXNativeTarget "KRKmeansTests" */ = { 568 | isa = XCConfigurationList; 569 | buildConfigurations = ( 570 | 8EE975641960257200335EB2 /* Debug */, 571 | 8EE975651960257200335EB2 /* Release */, 572 | ); 573 | defaultConfigurationIsVisible = 0; 574 | defaultConfigurationName = Release; 575 | }; 576 | /* End XCConfigurationList section */ 577 | }; 578 | rootObject = 8EE975261960257100335EB2 /* Project object */; 579 | } 580 | -------------------------------------------------------------------------------- /KRKmeans.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /KRKmeans.xcodeproj/project.xcworkspace/xcshareddata/KRKmeans.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | E57A2907-A074-4106-B530-22DF2BC0D9E7 9 | IDESourceControlProjectName 10 | project 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 0FD47910F037E012AA6F179F93F7DFEC0BB80E7B 14 | https://github.com/Kalvar/ios-KRKmeans-Algorithm.git 15 | 16 | IDESourceControlProjectPath 17 | KRKmeans.xcodeproj/project.xcworkspace 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 0FD47910F037E012AA6F179F93F7DFEC0BB80E7B 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/Kalvar/ios-KRKmeans-Algorithm.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 0FD47910F037E012AA6F179F93F7DFEC0BB80E7B 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 0FD47910F037E012AA6F179F93F7DFEC0BB80E7B 36 | IDESourceControlWCCName 37 | ios-KRKmeans-Algorithm 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /KRKmeans.xcodeproj/project.xcworkspace/xcuserdata/Kalvar.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kalvar/ios-KRKmeans-Algorithm/39e9f690df9885e20cb59989d05d8d9bb9748a97/KRKmeans.xcodeproj/project.xcworkspace/xcuserdata/Kalvar.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /KRKmeans.xcodeproj/project.xcworkspace/xcuserdata/Kalvar.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /KRKmeans.xcodeproj/xcuserdata/Kalvar.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /KRKmeans.xcodeproj/xcuserdata/Kalvar.xcuserdatad/xcschemes/KRKmeans.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 79 | 80 | 81 | 82 | 88 | 90 | 96 | 97 | 98 | 99 | 101 | 102 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /KRKmeans.xcodeproj/xcuserdata/Kalvar.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | KRKmeans.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 8EE9752D1960257200335EB2 16 | 17 | primary 18 | 19 | 20 | 8EE9754E1960257200335EB2 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /KRKmeans/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // KRKmeans V2.4.1 4 | // 5 | // Created by Kalvar on 2014/6/29. 6 | // Copyright (c) 2014 - 2015年 Kalvar Lin, ilovekalvar@gmail.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /KRKmeans/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // KRKmeans V2.4.1 4 | // 5 | // Created by Kalvar on 2014/6/29. 6 | // Copyright (c) 2014 - 2015年 Kalvar Lin, ilovekalvar@gmail.com. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @implementation AppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | // Override point for customization after application launch. 16 | return YES; 17 | } 18 | 19 | - (void)applicationWillResignActive:(UIApplication *)application 20 | { 21 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 22 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 23 | } 24 | 25 | - (void)applicationDidEnterBackground:(UIApplication *)application 26 | { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | - (void)applicationWillEnterForeground:(UIApplication *)application 32 | { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | - (void)applicationDidBecomeActive:(UIApplication *)application 37 | { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application 42 | { 43 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /KRKmeans/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /KRKmeans/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /KRKmeans/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /KRKmeans/KRKmeans-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /KRKmeans/KRKmeans-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | -------------------------------------------------------------------------------- /KRKmeans/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // KRKmeans V2.4.1 4 | // 5 | // Created by Kalvar on 2014/6/29. 6 | // Copyright (c) 2014 - 2015年 Kalvar Lin, ilovekalvar@gmail.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /KRKmeans/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // KRKmeans V2.4.1 4 | // 5 | // Created by Kalvar on 2014/6/29. 6 | // Copyright (c) 2014 - 2015年 Kalvar Lin, ilovekalvar@gmail.com. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "KRKmeans.h" 11 | 12 | @interface ViewController () 13 | 14 | @end 15 | 16 | @implementation ViewController (fixSamples) 17 | 18 | -(void)oneDemensionalClustering 19 | { 20 | //One dimensional K-Means, the data set is any number means. 21 | KRKmeansOne *kmeansOne = [KRKmeansOne sharedKmeans]; 22 | kmeansOne.sources = @[@0.33, @0.88, @1, @0.52, @146, @120, @45, @43, @0.4]; 23 | 24 | //If you wanna customize the median value 25 | //kmeansOne.customMedian = 45.0f; 26 | 27 | [kmeansOne clusteringWithCompletion:^(BOOL success, float knowledgeLine, NSArray *maxClusters, NSArray *minClusters, NSArray *midClusters, NSDictionary *overlappings) 28 | { 29 | NSLog(@"knowledgeLine : %f", knowledgeLine); 30 | NSLog(@"maxClusters : %@", maxClusters); 31 | NSLog(@"minClusters : %@", minClusters); 32 | NSLog(@"midClusters : %@", midClusters); 33 | NSLog(@"overlappings : %@", overlappings); 34 | //[_krKmeansOne printResults]; 35 | }]; 36 | /* 37 | Output : 38 | 39 | Conditions : 40 | n = 3 41 | Tmax = 146 42 | Tmin = 0.33 43 | Tmid = 1 44 | 45 | Answer : 46 | 47 | Max Clusters : 0.33, 0.52, 0.4 48 | Min Clusters : 0.88, 1, 45, 43 49 | Mid Clusters : 146, 120 50 | 51 | Knowledge Line : 52 | 53 | 63.110001 54 | */ 55 | } 56 | 57 | -(void)multiClustering 58 | { 59 | KRKmeans *kmeans = [KRKmeans sharedKmeans]; 60 | kmeans.modelKey = @"MyKmeans1"; 61 | kmeans.saveAfterDone = YES; 62 | kmeans.maxIteration = 10; 63 | 64 | // Adding patterns 65 | NSArray *patterns = @[@[@5, @4], @[@3, @4], @[@2, @5], @[@9, @8], @[@3, @20], 66 | @[@1, @1], @[@1, @2], @[@2, @2], @[@3, @2], @[@3, @1], 67 | @[@6, @4], @[@7, @6], @[@5, @6], @[@6, @5], @[@7, @8], 68 | @[@3, @12], @[@5, @20]]; 69 | NSInteger index = -1; 70 | for( NSArray *features in patterns ) 71 | { 72 | index += 1; 73 | NSString *patternId = [NSString stringWithFormat:@"Training_%li", index]; 74 | KRKmeansPattern *pattern = [kmeans createPatternWithFeatures:features patternId:patternId]; 75 | [kmeans addPattern:pattern]; 76 | } 77 | 78 | // @ About the groups and the centers that you have 2 methods to build : 79 | // 1. Random choosing centers from patterns 80 | [kmeans randomChooseCenters:3]; 81 | 82 | // 2. Quickly customizing the groups and centers 83 | //[kmeans addGroupForCenterFeatures:@[@2, @2] centerId:@"Center_1" groupId:@"Group_1"]; 84 | //[kmeans addGroupForCenterFeatures:@[@6, @5] centerId:@"Center_2" groupId:@"Group_2"]; 85 | //[kmeans addGroupForCenterFeatures:@[@3, @17] centerId:@"Center_3" groupId:@"Group_3"]; 86 | 87 | // @ Distance formula are : 88 | // KRKmeansKernelCosine is Cosine Similarity 89 | // KRKmeansKernelEuclidean is Euclidean 90 | // KRKmeansKernelRBF is Radial Basis Function 91 | [kmeans setupKernel:KRKmeansKernelEuclidean]; 92 | 93 | [kmeans clusteringWithCompletion:^(BOOL success, KRKmeans *kmeansObject, NSInteger totalTimes) { 94 | NSLog(@"totalTimes : %li", totalTimes); 95 | NSLog(@"featuresOfCenters : %@", kmeansObject.featuresOfCenters); 96 | NSLog(@"centers objects: %@", kmeansObject.centers); 97 | NSLog(@"SSE : %lf", kmeansObject.sse); 98 | } perIteration:^(NSInteger times, KRKmeans *kmeansObject, BOOL *pause) { 99 | NSLog(@"times : %li", times); 100 | // If you want to direct pause that next iteration running, then you could set : 101 | //*pause = YES; 102 | }]; 103 | 104 | } 105 | 106 | // Recovering the tranined groups to predicate patterns. 107 | -(void)predicatingByTrainedModel 108 | { 109 | KRKmeans *kmeans = [KRKmeans sharedKmeans]; 110 | [kmeans recoverGroupsForKey:@"MyKmeans1"]; 111 | 112 | NSMutableArray *samples = [NSMutableArray new]; 113 | NSArray *patterns = @[@[@21, @12], @[@13, @21], @[@12, @5], @[@3, @8]]; 114 | NSInteger index = -1; 115 | for( NSArray *features in patterns ) 116 | { 117 | index += 1; 118 | NSString *patternId = [NSString stringWithFormat:@"Predication_%li", index]; 119 | KRKmeansPattern *pattern = [kmeans createPatternWithFeatures:features patternId:patternId]; 120 | [samples addObject:pattern]; 121 | } 122 | 123 | [kmeans predicatePatterns:samples completion:^(BOOL success, KRKmeans *kmeansObject, NSInteger totalTimes) { 124 | NSLog(@"\n\n====================== Predication ===========================\n\n"); 125 | [kmeansObject printResults]; 126 | }]; 127 | 128 | } 129 | 130 | @end 131 | 132 | @implementation ViewController 133 | 134 | - (void)viewDidLoad 135 | { 136 | [super viewDidLoad]; 137 | [self oneDemensionalClustering]; 138 | [self multiClustering]; 139 | [self predicatingByTrainedModel]; 140 | } 141 | 142 | - (void)didReceiveMemoryWarning 143 | { 144 | [super didReceiveMemoryWarning]; 145 | } 146 | 147 | @end 148 | -------------------------------------------------------------------------------- /KRKmeans/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /KRKmeans/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // KRKmeans V2.4.1 4 | // 5 | // Created by Kalvar on 2014/6/29. 6 | // Copyright (c) 2014 - 2015年 Kalvar Lin, ilovekalvar@gmail.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "AppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /KRKmeansTests/KRKmeansTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /KRKmeansTests/KRKmeansTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeans V2.4.1Tests.m 3 | // KRKmeans V2.4.1Tests 4 | // 5 | // Created by Kalvar on 2014/6/29. 6 | // Copyright (c) 2014 - 2015年 Kalvar Lin, ilovekalvar@gmail.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KRKmeansTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation KRKmeansTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /KRKmeansTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 - 2016 Kuo-Ming Lin (Kalvar Lin) (http://kalvar-kaki.blogspot.tw/) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | 21 | ... bla bla ... 22 | Up to you anything you wanna do, I'm glad to help you. -------------------------------------------------------------------------------- /ML/KRKmeans.h: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeans.h 3 | // KRKmeans V2.4.1 4 | // 5 | // Created by Kalvar on 2014/6/30. 6 | // Copyright (c) 2014 - 2015年 Kalvar Lin, ilovekalvar@gmail.com. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "KRKmeansOne.h" 11 | #import "KRKmeansKernel.h" 12 | #import "KRKmeansGroup.h" 13 | 14 | @class KRKmeans; 15 | 16 | typedef void(^KRKmeansClusteringCompletion)(BOOL success, KRKmeans *kmeansObject, NSInteger totalTimes); 17 | typedef void(^KRKmeansPerIteration)(NSInteger times, KRKmeans *kmeansObject, BOOL *pause); 18 | 19 | @interface KRKmeans : NSObject 20 | 21 | // This modelKey used in saving that tained groups in KRKmeansSaver, 22 | // If it is nil or @"" before saving k-means trained groups, this modelKey will be automatic created by milliseconds of current timestamp. 23 | @property (nonatomic, strong) NSString *modelKey; 24 | // 每一個分類好的群聚 25 | @property (nonatomic, strong) NSMutableArray *classifiedGroups; 26 | // 要分群的集合數據 27 | @property (nonatomic, strong) NSMutableArray *patterns; 28 | // 每群的中心點物件, Center-objects of groups 29 | @property (nonatomic, readonly) NSArray *centers; 30 | // 每群的中心點特幑值, Features of centers of each groups 31 | @property (nonatomic, readonly) NSArray *featuresOfCenters; 32 | // 收斂誤差 33 | @property (nonatomic, assign) double convergenceError; 34 | // Max iterations of limitation 35 | @property (nonatomic, assign) NSInteger maxIteration; 36 | // Saving trained model after done 37 | @property (nonatomic, assign) BOOL saveAfterDone; 38 | // If we used RBF be the kernel that can setup this considition 39 | @property (nonatomic, assign) double sigma; 40 | @property (nonatomic, readonly) double sse; 41 | @property (nonatomic, readonly) BOOL isPaused; 42 | 43 | @property (nonatomic, copy) KRKmeansClusteringCompletion clusterCompletion; 44 | @property (nonatomic, copy) KRKmeansPerIteration perIteration; 45 | 46 | + (instancetype)sharedKmeans; 47 | - (instancetype)init; 48 | 49 | - (KRKmeansPattern *)createPatternWithFeatures:(NSArray *)features patternId:(NSString *)patternId; 50 | - (KRKmeansCenter *)createCenterWithFeatures:(NSArray *)features centerId:(NSString *)centerId; 51 | - (KRKmeansGroup *)createGroupWithCenter:(KRKmeansCenter *)groupCenter ownPatterns:(NSArray *)groupPatterns groupId:(NSString *)groupId; 52 | 53 | - (void)addGroup:(KRKmeansGroup *)group copy:(BOOL)copy; 54 | - (void)addGroup:(KRKmeansGroup *)group; 55 | - (void)addGroupForCenterFeatures:(NSArray *)centerFeatures centerId:(NSString *)centerId groupId:(NSString *)groupId; 56 | - (void)addPattern:(KRKmeansPattern *)pattern forGroupId:(NSString *)groupId; 57 | - (void)addPattern:(KRKmeansPattern *)pattern; 58 | - (void)addPatterns:(NSArray *)samples; 59 | - (void)addPatternWithFeatures:(NSArray *)features patternId:(NSString *)patternId; 60 | 61 | - (void)randomChooseCenters:(NSInteger)chooseNumber; // 隨機選取中心點 62 | - (void)predicatePatterns:(NSArray *)samples completion:(KRKmeansClusteringCompletion)completion; 63 | - (void)clusteringWithCompletion:(KRKmeansClusteringCompletion)completion perIteration:(KRKmeansPerIteration)iteration; 64 | 65 | - (void)pause; 66 | - (void)restart; 67 | 68 | - (void)recoverGroupsForKey:(NSString *)saveKey; 69 | - (void)printResults; 70 | 71 | - (void)setupKernel:(KRKmeansKernels)kernel; // 要用哪個算法進行分類 72 | 73 | - (void)setClusterCompletion:(KRKmeansClusteringCompletion)block; 74 | - (void)setPerIteration:(KRKmeansPerIteration)block; 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /ML/KRKmeans.m: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeans.m 3 | // KRKmeans V2.4.1 4 | // 5 | // Created by Kalvar on 2014/6/30. 6 | // Copyright (c) 2014 - 2015年 Kalvar Lin, ilovekalvar@gmail.com. All rights reserved. 7 | // 8 | 9 | #import "KRKmeans.h" 10 | #import "NSArray+Statistics.h" 11 | #import "KRKmeansSaver.h" 12 | 13 | @interface KRKmeans () 14 | 15 | // 當前的迭代數 16 | @property (nonatomic, assign) NSInteger currentIteration; 17 | // 儲存訓練好的群心 18 | @property (nonatomic, strong) KRKmeansSaver *saver; 19 | @property (nonatomic, strong) KRKmeansKernel *kernel; 20 | 21 | @end 22 | 23 | @implementation KRKmeans (Sorting) 24 | // 用洗牌法進行亂數取出 25 | - (NSArray *)randomizeArray:(NSArray *)_patterns 26 | { 27 | NSMutableArray *_samples = [_patterns mutableCopy]; 28 | NSInteger _totalLength = [_patterns count]; 29 | for( NSInteger _i=0; _i<_totalLength; _i++ ) 30 | { 31 | NSInteger _random1 = ( arc4random() % _totalLength ); 32 | NSInteger _random2 = ( arc4random() % _totalLength ); 33 | // 如果亂數重複,則用範本數長度減去亂數值 34 | if( _random1 == _random2 ) 35 | { 36 | _random2 = _totalLength - _random2; 37 | } 38 | // 進行陣列交換 39 | // 先取出 random1 位置的 Object 40 | NSArray *_temp = [_samples objectAtIndex:_random1]; 41 | // 再將 random2 位置的 Object 塞回去 random1 位置 42 | [_samples replaceObjectAtIndex:_random1 withObject:[_samples objectAtIndex:_random2]]; 43 | // 最後將剛才取出的 random1 Object 塞回去 random2 即可 44 | [_samples replaceObjectAtIndex:_random2 withObject:_temp]; 45 | } 46 | return _samples; 47 | } 48 | 49 | @end 50 | 51 | @implementation KRKmeans (Clustering) 52 | 53 | - (void)operateCompletionBlockForSuccess:(BOOL)success 54 | { 55 | if( self.clusterCompletion ) 56 | { 57 | self.clusterCompletion(success, self, self.currentIteration); 58 | } 59 | } 60 | 61 | - (void)operateIterationBlock 62 | { 63 | if( self.perIteration ) 64 | { 65 | // TODO: the *pause BOOL implmentation ... if possible 66 | BOOL pause = NO; 67 | self.perIteration(self.currentIteration, self, &pause); 68 | if( pause ) 69 | { 70 | [self pause]; 71 | } 72 | } 73 | } 74 | 75 | - (void)removeAllClassifiedPatterns 76 | { 77 | [self.classifiedGroups enumerateObjectsUsingBlock:^(KRKmeansGroup * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 78 | [obj removeAllPatterns]; 79 | }]; 80 | } 81 | 82 | // 計算要分到哪一個最小距離的 Center 去要分到哪一個最小距離的 Center 去 (算每一個 Pattern 對每一個 Center 的距離) 83 | - (void)clusteringToGroupWithPatterns:(NSArray *)samples 84 | { 85 | // 計算該 Pattern 要被分到哪一個中心點去 86 | for( KRKmeansPattern *pattern in samples ) 87 | { 88 | NSInteger groupIndex = -1; 89 | NSInteger toIndex = -1; 90 | double minDistance = 0.0f; 91 | for( KRKmeansGroup *group in self.classifiedGroups ) 92 | { 93 | groupIndex += 1; 94 | // 計算到該 Pattern 到該 Group Center 的距離 95 | double distance = [group distanceCenterToFeatures:pattern.features]; 96 | if( toIndex < 0 || distance < minDistance ) 97 | { 98 | minDistance = distance; 99 | toIndex = groupIndex; 100 | } 101 | } 102 | 103 | // 分到指定的群裡 104 | if( toIndex >= 0 ) 105 | { 106 | KRKmeansGroup *toGroup = [self.classifiedGroups objectAtIndex:toIndex]; 107 | [toGroup addPattern:pattern]; 108 | } 109 | } 110 | } 111 | 112 | - (void)training 113 | { 114 | if( self.isPaused || [self.patterns count] == 0 ) 115 | { 116 | [self operateCompletionBlockForSuccess:NO]; 117 | return; 118 | } 119 | /* 120 | * @ Steps 121 | * 1. 全部分類 122 | * 2. 重新計算每一個群聚的中心點 123 | * 3. 計算該次迭代的所有群聚中心點與上一次舊的群聚中心點相減,取出最大距離誤差 124 | * 4. 比較新舊最大距離誤差是否 <= 收斂誤差,如是,即停止運算,如否,則進行第 4 步驟的遞迴迭代運算 125 | * 5. 依照這群聚中心點,進行迭代運算,重新計算與分類所有的已分類好的群聚,並重複第 1 到第 4 步驟 126 | */ 127 | [self removeAllClassifiedPatterns]; 128 | [self clusteringToGroupWithPatterns:self.patterns]; 129 | 130 | // 計算上一次 Centers 跟當前 Centers 的最大距離差值 131 | __block double differenceDistance = -1.0f; 132 | [self.classifiedGroups enumerateObjectsUsingBlock:^(KRKmeansGroup * _Nonnull group, NSUInteger idx, BOOL * _Nonnull stop) { 133 | // Renew all centers 134 | [group renewCenter]; 135 | // 計算新舊群聚中心點的距離 136 | double distance = [group centerDifference]; 137 | // 距離差值 < 0.0f || 距離 > 距離差值 138 | if( differenceDistance < 0.0f || distance > differenceDistance ) 139 | { 140 | differenceDistance = distance; 141 | } 142 | }]; 143 | 144 | // abs(當前中心點最大距離上次距離的誤差) <= 收斂值 || 迭代運算到了限定次數 ( 避免 Memory Leak ) 145 | if( fabs(differenceDistance) <= self.convergenceError || self.currentIteration >= self.maxIteration ) 146 | { 147 | // 已達收斂條件 148 | //NSLog(@"收斂迭代[%li], 前後中心點距離誤差 %f", self.currentIteration, differenceDistance); 149 | if( self.saveAfterDone ) 150 | { 151 | [self.saver save:self.classifiedGroups forKey:self.modelKey]; 152 | } 153 | [self operateCompletionBlockForSuccess:YES]; 154 | } 155 | else 156 | { 157 | self.currentIteration += 1; 158 | [self operateIterationBlock]; 159 | [self training]; 160 | } 161 | } 162 | 163 | @end 164 | 165 | @implementation KRKmeans 166 | 167 | + (instancetype)sharedKmeans 168 | { 169 | static dispatch_once_t pred; 170 | static KRKmeans *_object = nil; 171 | dispatch_once(&pred, ^{ 172 | _object = [[KRKmeans alloc] init]; 173 | }); 174 | return _object; 175 | } 176 | 177 | - (instancetype)init 178 | { 179 | self = [super init]; 180 | if( self ) 181 | { 182 | _classifiedGroups = [NSMutableArray new]; 183 | _patterns = [NSMutableArray new]; 184 | _convergenceError = 0.001f; 185 | _maxIteration = 5000; 186 | _saveAfterDone = NO; 187 | 188 | _clusterCompletion = nil; 189 | _perIteration = nil; 190 | 191 | _currentIteration = 0; 192 | 193 | _saver = [[KRKmeansSaver alloc] init]; 194 | _kernel = [[KRKmeansKernel alloc] init]; 195 | 196 | _isPaused = NO; 197 | 198 | } 199 | return self; 200 | } 201 | 202 | #pragma mark - Creating 203 | - (KRKmeansPattern *)createPatternWithFeatures:(NSArray *)features patternId:(NSString *)patternId 204 | { 205 | return [[KRKmeansPattern alloc] initWithFeatures:features identifier:patternId]; 206 | } 207 | 208 | - (KRKmeansCenter *)createCenterWithFeatures:(NSArray *)features centerId:(NSString *)centerId 209 | { 210 | return [[KRKmeansCenter alloc] initWithFeatures:features identifier:centerId]; 211 | } 212 | 213 | - (KRKmeansGroup *)createGroupWithCenter:(KRKmeansCenter *)groupCenter ownPatterns:(NSArray *)groupPatterns groupId:(NSString *)groupId 214 | { 215 | KRKmeansGroup *group = [[KRKmeansGroup alloc] initWithPatterns:groupPatterns groupId:groupId]; 216 | [group setCenter:groupCenter]; 217 | return group; 218 | } 219 | 220 | #pragma mark - Adding 221 | - (void)addGroup:(KRKmeansGroup *)group copy:(BOOL)copy 222 | { 223 | [_classifiedGroups addObject:( copy ? [group copy] : group )]; 224 | } 225 | 226 | - (void)addGroup:(KRKmeansGroup *)group 227 | { 228 | [self addGroup:group copy:NO]; 229 | } 230 | 231 | // To create new group with custom center. 232 | - (void)addGroupForCenterFeatures:(NSArray *)centerFeatures centerId:(NSString *)centerId groupId:(NSString *)groupId 233 | { 234 | KRKmeansCenter *center = [self createCenterWithFeatures:centerFeatures centerId:centerId]; 235 | KRKmeansGroup *group = [self createGroupWithCenter:center ownPatterns:nil groupId:groupId]; 236 | [self addGroup:group]; 237 | } 238 | 239 | - (void)addPattern:(KRKmeansPattern *)pattern forGroupId:(NSString *)groupId 240 | { 241 | if( nil == pattern ) 242 | { 243 | return; 244 | } 245 | 246 | [_patterns addObject:pattern]; 247 | if( nil != groupId && [groupId length] > 0 ) 248 | { 249 | for( KRKmeansGroup *group in _classifiedGroups ) 250 | { 251 | if( [group.identifier isEqualToString:groupId] ) 252 | { 253 | [group addPattern:pattern]; 254 | break; 255 | } 256 | } 257 | } 258 | } 259 | 260 | - (void)addPattern:(KRKmeansPattern *)pattern 261 | { 262 | [self addPattern:pattern forGroupId:nil]; 263 | } 264 | 265 | - (void)addPatterns:(NSArray *)samples 266 | { 267 | __weak typeof(self) weakSelf = self; 268 | [samples enumerateObjectsUsingBlock:^(KRKmeansPattern * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 269 | [weakSelf addPattern:obj]; 270 | }]; 271 | } 272 | 273 | - (void)addPatternWithFeatures:(NSArray *)features patternId:(NSString *)patternId 274 | { 275 | KRKmeansPattern *pattern = [self createPatternWithFeatures:features patternId:patternId]; 276 | [self addPattern:pattern]; 277 | } 278 | 279 | #pragma mark - Training & Clustering 280 | // 依期望分幾群來進行隨機自動分群的中心點選擇,如 _pickNumber 代入 0 則為完全由系統決定的隨機分群 281 | // 如有在外部使用此函式,就能不必再設定 autoClusterNumber 282 | - (void)randomChooseCenters:(NSInteger)chooseNumber 283 | { 284 | NSInteger totalLength = [_patterns count]; 285 | // 先正規化 pickNumber 以避免 <= 0 和 > _totalLength 的狀況 286 | if( chooseNumber <= 0 || chooseNumber > totalLength ) 287 | { 288 | chooseNumber = ( arc4random() % totalLength ); 289 | } 290 | 291 | NSArray *randomizedPatterns = [self randomizeArray:_patterns]; 292 | for( NSInteger i = 0; i < chooseNumber; ++i ) 293 | { 294 | NSString *tempId = [NSString stringWithFormat:@"%li", i]; 295 | KRKmeansPattern *pattern = [randomizedPatterns objectAtIndex:i]; 296 | KRKmeansCenter *center = [self createCenterWithFeatures:pattern.features centerId:tempId]; 297 | KRKmeansGroup *group = [self createGroupWithCenter:center ownPatterns:nil groupId:tempId]; 298 | [self addGroup:group]; 299 | } 300 | } 301 | 302 | - (void)predicatePatterns:(NSArray *)samples completion:(KRKmeansClusteringCompletion)completion 303 | { 304 | if( nil != samples && [samples count] > 0 ) 305 | { 306 | [self removeAllClassifiedPatterns]; 307 | [self clusteringToGroupWithPatterns:samples]; 308 | if( completion ) 309 | { 310 | completion(YES, self, 1); 311 | } 312 | } 313 | } 314 | 315 | - (void)clusteringWithCompletion:(KRKmeansClusteringCompletion)completion perIteration:(KRKmeansPerIteration)iteration 316 | { 317 | _clusterCompletion = completion; 318 | _perIteration = iteration; 319 | _currentIteration = 0; 320 | _isPaused = NO; 321 | [self training]; 322 | } 323 | 324 | #pragma mark - Status 325 | - (void)pause 326 | { 327 | _isPaused = YES; 328 | } 329 | 330 | - (void)restart 331 | { 332 | _isPaused = NO; 333 | [self training]; 334 | } 335 | 336 | - (void)reset 337 | { 338 | _isPaused = NO; 339 | [_classifiedGroups removeAllObjects]; 340 | [_patterns removeAllObjects]; 341 | _clusterCompletion = nil; 342 | _perIteration = nil; 343 | _currentIteration = 0; 344 | _maxIteration = 0; 345 | _saveAfterDone = NO; 346 | } 347 | 348 | #pragma mark - Results 349 | // Recovering that trained groups from KRKmeansSaver for self.identifier (the model key). 350 | - (void)recoverGroupsForKey:(NSString *)saveKey 351 | { 352 | NSMutableArray *savedGroups = [_saver objectForKey:saveKey]; 353 | [_classifiedGroups removeAllObjects]; 354 | [_classifiedGroups addObjectsFromArray:savedGroups]; 355 | } 356 | 357 | - (void)printResults 358 | { 359 | [_classifiedGroups enumerateObjectsUsingBlock:^(KRKmeansGroup * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 360 | NSLog(@"Clustering Group ID is %@, its own patterns are as below :", obj.identifier); 361 | NSLog(@"Center ID is %@, its features are %@", obj.center.identifier, obj.center.features); 362 | [obj.patterns enumerateObjectsUsingBlock:^(KRKmeansPattern * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 363 | NSLog(@"Pattern ID is %@", obj.identifier); 364 | NSLog(@"Features are %@", obj.features); 365 | }]; 366 | NSLog(@"====================================\n\n"); 367 | }]; 368 | } 369 | 370 | - (void)setupKernel:(KRKmeansKernels)kernel 371 | { 372 | [_classifiedGroups enumerateObjectsUsingBlock:^(KRKmeansGroup * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 373 | obj.kernel = kernel; 374 | }]; 375 | } 376 | 377 | #pragma mark - Blocks 378 | -(void)setClusterCompletion:(KRKmeansClusteringCompletion)block 379 | { 380 | _clusterCompletion = block; 381 | } 382 | 383 | -(void)setPerIteration:(KRKmeansPerIteration)block 384 | { 385 | _perIteration = block; 386 | } 387 | 388 | #pragma mark - Getters 389 | - (NSString *)modelKey 390 | { 391 | if( nil == _modelKey || [_modelKey length] == 0 ) 392 | { 393 | // Using that milliseconds timestamp to be identifier of this k-means model. 394 | _modelKey = [NSString stringWithFormat:@"%lf", [[NSDate date] timeIntervalSince1970] * 1000.0f]; 395 | } 396 | return _modelKey; 397 | } 398 | 399 | - (NSArray *)centers 400 | { 401 | if( _classifiedGroups && [_classifiedGroups count] > 0 ) 402 | { 403 | NSMutableArray *groupCenters = [NSMutableArray new]; 404 | for( KRKmeansGroup *group in _classifiedGroups ) 405 | { 406 | [groupCenters addObject:group.center]; 407 | } 408 | return groupCenters; 409 | } 410 | return nil; 411 | } 412 | 413 | - (NSArray *)featuresOfCenters 414 | { 415 | NSMutableArray *features = nil; 416 | NSArray *groupCenters = self.centers; 417 | if( nil != groupCenters ) 418 | { 419 | features = [NSMutableArray new]; 420 | for( KRKmeansCenter *center in groupCenters ) 421 | { 422 | [features addObject:center.features]; 423 | } 424 | } 425 | return features; 426 | } 427 | 428 | // SSE, 計算加總所有的分群裡頭每個資料點與中心點距離,用於對每次 K-Means 的聚類結果做評量,以找出具有最小SSE的那組聚類結果作為解答 429 | -(double)sse 430 | { 431 | __block double sumSSE = 0.0f; 432 | if( _classifiedGroups ) 433 | { 434 | [_classifiedGroups enumerateObjectsUsingBlock:^(KRKmeansGroup * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) { 435 | sumSSE += obj.groupDistance; 436 | }]; 437 | } 438 | return sumSSE; 439 | } 440 | 441 | #pragma mark - Setters 442 | - (void)setSigma:(double)sigma 443 | { 444 | if( _classifiedGroups ) 445 | { 446 | for( KRKmeansGroup *group in _classifiedGroups ) 447 | { 448 | group.sigma = sigma; 449 | } 450 | } 451 | } 452 | 453 | @end 454 | -------------------------------------------------------------------------------- /ML/KRKmeansGroup/KRKmeansCenter/KRKmeansCenter.h: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeansCenter.h 3 | // KRKmeans 4 | // 5 | // Created by Kalvar Lin on 2016/6/4. 6 | // Copyright © 2016年 Kalvar. All rights reserved. 7 | // 8 | 9 | #import "KRKmeansPattern.h" 10 | 11 | @interface KRKmeansCenter : KRKmeansPattern 12 | 13 | - (instancetype)initWithFeatures:(NSArray *)f identifier:(NSString *)i; 14 | - (void)addOneFeature:(NSNumber *)oneFeature; 15 | - (void)addFeaturesFromArray:(NSArray *)f; 16 | - (void)removeAllFeatures; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /ML/KRKmeansGroup/KRKmeansCenter/KRKmeansCenter.m: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeansCenter.m 3 | // KRKmeans 4 | // 5 | // Created by Kalvar Lin on 2016/6/4. 6 | // Copyright © 2016年 Kalvar. All rights reserved. 7 | // 8 | 9 | #import "KRKmeansCenter.h" 10 | 11 | @implementation KRKmeansCenter 12 | 13 | - (instancetype)initWithFeatures:(NSArray *)f identifier:(NSString *)i 14 | { 15 | self = [super initWithFeatures:f identifier:i]; 16 | if( self ) 17 | { 18 | 19 | } 20 | return self; 21 | } 22 | 23 | - (void)addOneFeature:(NSNumber *)oneFeature 24 | { 25 | [self.features addObject:[oneFeature copy]]; 26 | } 27 | 28 | - (void)addFeaturesFromArray:(NSArray *)f 29 | { 30 | [self.features addObjectsFromArray:f]; 31 | } 32 | 33 | - (void)removeAllFeatures 34 | { 35 | [self.features removeAllObjects]; 36 | } 37 | 38 | -(instancetype)copyWithZone:(NSZone *)zone 39 | { 40 | KRKmeansCenter *p = [[KRKmeansCenter alloc] init]; 41 | p.features = [[NSMutableArray alloc] initWithArray:self.features copyItems:YES]; 42 | p.identifier = self.identifier; 43 | return p; 44 | } 45 | 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /ML/KRKmeansGroup/KRKmeansGroup.h: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeansGroup.h 3 | // KRKmeans 4 | // 5 | // Created by Kalvar Lin on 2016/6/4. 6 | // Copyright © 2016年 Kalvar. All rights reserved. 7 | // 8 | 9 | #import "KRKmeansCenter.h" 10 | #import "KRKmeansKernel.h" 11 | 12 | @interface KRKmeansGroup : NSObject 13 | 14 | // 群組的代表 ID 15 | @property (nonatomic, strong) NSString *identifier; 16 | // 在這群組裡的數據組 17 | @property (nonatomic, strong) NSMutableArray *patterns; 18 | // 這群組的當前中心點 (也為 New Center) 19 | @property (nonatomic, strong) KRKmeansCenter *center; 20 | // 這群組的上一次中心點 21 | @property (nonatomic, strong) KRKmeansCenter *lastCenter; 22 | // 距離運算方法 23 | @property (nonatomic, assign) KRKmeansKernels kernel; 24 | // Kernel Sigma of RBF 25 | @property (nonatomic, assign) double sigma; 26 | 27 | - (instancetype)initWithPatterns:(NSArray *)samples groupId:(NSString *)groupId; 28 | - (instancetype)init; 29 | 30 | - (void)addPattern:(KRKmeansPattern *)pattern; 31 | - (void)addPatterns:(NSArray *)batchPatterns; 32 | - (void)renewCenter; 33 | - (void)removeAllPatterns; 34 | - (void)resetCenters; 35 | 36 | - (double)distanceX1:(NSArray *)x1 x2:(NSArray *)x2; 37 | - (double)distanceCenterToFeatures:(NSArray *)features; 38 | - (double)centerDifference; 39 | - (double)groupDistance; 40 | 41 | @end -------------------------------------------------------------------------------- /ML/KRKmeansGroup/KRKmeansGroup.m: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeansGroup.m 3 | // KRKmeans 4 | // 5 | // Created by Kalvar Lin on 2016/6/4. 6 | // Copyright © 2016年 Kalvar. All rights reserved. 7 | // 8 | 9 | #import "KRKmeansGroup.h" 10 | 11 | @interface KRKmeansGroup () 12 | 13 | @property (nonatomic, strong) KRKmeansKernel *calculator; 14 | @property (nonatomic, weak) NSCoder *coder; 15 | 16 | @end 17 | 18 | @implementation KRKmeansGroup (NSCoding) 19 | 20 | - (void)encodeObject:(id)object forKey:(NSString *)key 21 | { 22 | if( nil != object ) 23 | { 24 | [self.coder encodeObject:object forKey:key]; 25 | } 26 | } 27 | 28 | - (id)decodeForKey:(NSString *)key 29 | { 30 | return [self.coder decodeObjectForKey:key]; 31 | } 32 | 33 | @end 34 | 35 | @implementation KRKmeansGroup 36 | 37 | - (instancetype)initWithPatterns:(NSArray *)samples groupId:(NSString *)groupId 38 | { 39 | self = [super init]; 40 | if( self ) 41 | { 42 | _identifier = groupId; 43 | 44 | _patterns = [NSMutableArray new]; 45 | [self addPatterns:samples]; 46 | 47 | _center = nil; 48 | _lastCenter = nil; 49 | 50 | _calculator = [[KRKmeansKernel alloc] init]; 51 | self.kernel = KRKmeansKernelEuclidean; 52 | self.sigma = 2.0f; 53 | } 54 | return self; 55 | } 56 | 57 | - (instancetype)init 58 | { 59 | return [self initWithPatterns:nil groupId:@""]; 60 | } 61 | 62 | - (void)addPattern:(KRKmeansPattern *)pattern 63 | { 64 | if( nil == pattern ) 65 | { 66 | return; 67 | } 68 | // To use weak reference with outside patterns. 69 | [_patterns addObject:pattern]; 70 | } 71 | 72 | - (void)addPatterns:(NSArray *)batchPatterns 73 | { 74 | if( nil == batchPatterns ) 75 | { 76 | return; 77 | } 78 | [_patterns addObjectsFromArray:batchPatterns]; 79 | } 80 | 81 | - (void)renewCenter 82 | { 83 | _lastCenter = [_center copy]; 84 | if( nil == _patterns || [_patterns count] == 0 ) 85 | { 86 | return; 87 | } 88 | 89 | [_center removeAllFeatures]; 90 | // To average multi-dimensional sub-vectors be central vectors 91 | NSInteger patternCount = [_patterns count]; 92 | // 取出 Pattern 裡的 Features 個數 93 | KRKmeansPattern *firstPattern = [_patterns firstObject]; 94 | NSInteger featuresCount = [firstPattern.features count]; 95 | for( NSInteger i=0; i 0 ) 144 | { 145 | for( KRKmeansPattern *pattern in _patterns ) 146 | { 147 | sum += [self distanceX1:pattern.features x2:_center.features]; 148 | } 149 | } 150 | return sum; 151 | } 152 | 153 | #pragma mark - Setters 154 | - (void)setKernel:(KRKmeansKernels)kernel 155 | { 156 | if( _calculator ) 157 | { 158 | _calculator.kernel = kernel; 159 | } 160 | } 161 | 162 | - (void)setSigma:(double)sigma 163 | { 164 | if( _calculator ) 165 | { 166 | _calculator.sigma = sigma; 167 | } 168 | } 169 | 170 | // Copy that setting center. 171 | - (void)setCenter:(KRKmeansCenter *)center 172 | { 173 | _center = ( nil != center ) ? [center copy] : center; 174 | } 175 | 176 | #pragma mark - Getters 177 | - (KRKmeansKernels)kernel 178 | { 179 | return _calculator ? _calculator.kernel : KRKmeansKernelEuclidean; 180 | } 181 | 182 | - (double)sigma 183 | { 184 | return _calculator ? _calculator.sigma : 0.0f; 185 | } 186 | 187 | #pragma --mark NSCoding 188 | -(void)encodeWithCoder:(NSCoder *)aCoder 189 | { 190 | self.coder = aCoder; 191 | [self encodeObject:_identifier forKey:@"identifier"]; 192 | [self encodeObject:_center forKey:@"center"]; 193 | [self encodeObject:_calculator forKey:@"calculator"]; // Kernel & Sigma are use in KRKmeansKernel. 194 | } 195 | 196 | -(instancetype)initWithCoder:(NSCoder *)aDecoder 197 | { 198 | self = [super init]; 199 | if(self) 200 | { 201 | self.coder = aDecoder; 202 | _identifier = [self decodeForKey:@"identifier"]; 203 | _center = [self decodeForKey:@"center"]; 204 | _calculator = [self decodeForKey:@"calculator"]; 205 | 206 | // Don't forget to alloc new memory for them since we didn't save it with self.coder before. 207 | _patterns = [NSMutableArray new]; 208 | } 209 | return self; 210 | } 211 | 212 | @end 213 | 214 | 215 | -------------------------------------------------------------------------------- /ML/KRKmeansGroup/KRKmeansPattern/KRKmeansPattern.h: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeansPattern.h 3 | // KRKmeans 4 | // 5 | // Created by Kalvar Lin on 2016/6/4. 6 | // Copyright © 2016年 Kalvar. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KRKmeansPattern : NSObject 12 | 13 | @property (nonatomic, strong) NSMutableArray *features; 14 | @property (nonatomic, strong) NSString *identifier; 15 | 16 | @property (nonatomic, weak) NSCoder *coder; // For NSCoding usage and child-class use in inherited this class. 17 | 18 | - (instancetype)initWithFeatures:(NSArray *)f identifier:(NSString *)i; 19 | 20 | @end 21 | 22 | @interface KRKmeansPattern (NSCoding) 23 | 24 | - (void)encodeObject:(id)object forKey:(NSString *)key; 25 | - (id)decodeForKey:(NSString *)key; 26 | 27 | @end -------------------------------------------------------------------------------- /ML/KRKmeansGroup/KRKmeansPattern/KRKmeansPattern.m: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeansPattern.m 3 | // KRKmeans 4 | // 5 | // Created by Kalvar Lin on 2016/6/4. 6 | // Copyright © 2016年 Kalvar. All rights reserved. 7 | // 8 | 9 | #import "KRKmeansPattern.h" 10 | 11 | @implementation KRKmeansPattern (NSCoding) 12 | 13 | - (void)encodeObject:(id)object forKey:(NSString *)key 14 | { 15 | if( nil != object ) 16 | { 17 | [self.coder encodeObject:object forKey:key]; 18 | } 19 | } 20 | 21 | - (id)decodeForKey:(NSString *)key 22 | { 23 | return [self.coder decodeObjectForKey:key]; 24 | } 25 | 26 | @end 27 | 28 | @implementation KRKmeansPattern 29 | 30 | - (instancetype)initWithFeatures:(NSArray *)f identifier:(NSString *)i 31 | { 32 | self = [super init]; 33 | if( self ) 34 | { 35 | _features = [[NSMutableArray alloc] initWithArray:f copyItems:YES]; 36 | _identifier = i; 37 | } 38 | return self; 39 | } 40 | 41 | #pragma --mark NSCopying 42 | -(instancetype)copyWithZone:(NSZone *)zone 43 | { 44 | KRKmeansPattern *p = [[KRKmeansPattern alloc] init]; 45 | p.features = [[NSMutableArray alloc] initWithArray:_features copyItems:YES]; 46 | p.identifier = _identifier; 47 | return p; 48 | } 49 | 50 | #pragma --mark NSCoding 51 | -(void)encodeWithCoder:(NSCoder *)aCoder 52 | { 53 | self.coder = aCoder; 54 | [self encodeObject:_features forKey:@"features"]; 55 | [self encodeObject:_identifier forKey:@"identifier"]; 56 | } 57 | 58 | -(instancetype)initWithCoder:(NSCoder *)aDecoder 59 | { 60 | self = [super init]; 61 | if(self) 62 | { 63 | self.coder = aDecoder; 64 | _features = [self decodeForKey:@"features"]; 65 | _identifier = [self decodeForKey:@"identifier"]; 66 | } 67 | return self; 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /ML/KRKmeansKernel/KRKmeansKernel.h: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeansKernel.h 3 | // KRKmeans 4 | // 5 | // Created by Kalvar Lin on 2016/6/4. 6 | // Copyright © 2016年 Kalvar. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // Distance formula 12 | typedef NS_ENUM(NSInteger, KRKmeansKernels) 13 | { 14 | // Cosine Similarity 15 | KRKmeansKernelCosine = 0, 16 | // Euclidean 17 | KRKmeansKernelEuclidean = 1, 18 | // Radial Basis Function 19 | KRKmeansKernelRBF = 2 20 | }; 21 | 22 | @interface KRKmeansKernel : NSObject 23 | 24 | @property (nonatomic, assign) KRKmeansKernels kernel; 25 | @property (nonatomic, assign) double sigma; 26 | 27 | - (instancetype)initWithKernel:(KRKmeansKernels)useKernel; 28 | - (instancetype)init; 29 | 30 | - (double)euclideanX1:(NSArray *)_x1 x2:(NSArray *)_x2; 31 | - (double)cosineSimilarityX1:(NSArray *)_x1 x2:(NSArray *)_x2; 32 | - (double)rbf:(NSArray *)_x1 x2:(NSArray *)_x2 sigma:(double)_sigma; 33 | - (double)distanceBetweenX1:(NSArray *)_x1 x2:(NSArray *)_x2; 34 | 35 | - (NSInteger)randomIntegerWithMax:(NSInteger)_maxValue min:(NSInteger)_minValue; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /ML/KRKmeansKernel/KRKmeansKernel.m: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeansKernel.m 3 | // KRKmeans 4 | // 5 | // Created by Kalvar Lin on 2016/6/4. 6 | // Copyright © 2016年 Kalvar. All rights reserved. 7 | // 8 | 9 | #import "KRKmeansKernel.h" 10 | 11 | @interface KRKmeansKernel () 12 | 13 | @property (nonatomic, weak) NSCoder *coder; 14 | 15 | @end 16 | 17 | @implementation KRKmeansKernel (NSCoding) 18 | 19 | - (void)encodeObject:(id)object forKey:(NSString *)key 20 | { 21 | if( nil != object ) 22 | { 23 | [self.coder encodeObject:object forKey:key]; 24 | } 25 | } 26 | 27 | - (id)decodeForKey:(NSString *)key 28 | { 29 | return [self.coder decodeObjectForKey:key]; 30 | } 31 | 32 | @end 33 | 34 | @implementation KRKmeansKernel 35 | 36 | - (instancetype)initWithKernel:(KRKmeansKernels)useKernel 37 | { 38 | self = [super init]; 39 | if( self ) 40 | { 41 | _kernel = useKernel; 42 | _sigma = 2.0f; 43 | } 44 | return self; 45 | } 46 | 47 | - (instancetype)init 48 | { 49 | return [self initWithKernel:KRKmeansKernelEuclidean]; 50 | } 51 | 52 | // Euclidean distance which multi-dimensional formula, 距離越小越近 53 | - (double)euclideanX1:(NSArray *)_x1 x2:(NSArray *)_x2 54 | { 55 | NSInteger _index = 0; 56 | double _sum = 0.0f; 57 | for( NSNumber *_x in _x1 ) 58 | { 59 | _sum += powf([_x doubleValue] - [[_x2 objectAtIndex:_index] doubleValue], 2); 60 | ++_index; 61 | } 62 | // 累加完距離後直接開根號 63 | return (_index > 0) ? sqrtf(_sum) : _sum; 64 | } 65 | 66 | // Cosine Similarity method that multi-dimensional, 同歸屬度越大越近 67 | - (double)cosineSimilarityX1:(NSArray *)_x1 x2:(NSArray *)_x2 68 | { 69 | double _sumA = 0.0f; 70 | double _sumB = 0.0f; 71 | double _sumAB = 0.0f; 72 | NSInteger _index = 0; 73 | for( NSNumber *_featureValue in _x1 ) 74 | { 75 | NSNumber *_trainValue = [_x2 objectAtIndex:_index]; 76 | float _aValue = [_featureValue doubleValue]; 77 | float _bValue = [_trainValue doubleValue]; 78 | _sumA += ( _aValue * _aValue ); 79 | _sumB += ( _bValue * _bValue ); 80 | _sumAB += ( _aValue * _bValue ); 81 | ++_index; 82 | } 83 | float _ab = _sumA * _sumB; 84 | return ( _ab > 0.0f ) ? ( _sumAB / sqrtf( _ab ) ) : 0.0f; 85 | } 86 | 87 | - (double)rbf:(NSArray *)_x1 x2:(NSArray *)_x2 sigma:(double)_rbfSigma 88 | { 89 | double _sum = 0.0f; 90 | NSInteger _index = 0; 91 | for( NSNumber *_value in _x1 ) 92 | { 93 | // Formula : s = s + ( v1[i] - v2[i] )^2 94 | double _v = [_value doubleValue] - [[_x2 objectAtIndex:_index] doubleValue]; 95 | _sum += ( _v * _v ); 96 | ++_index; 97 | } 98 | // Formula : exp^( -s / ( 2.0f * sigma * sigma ) ) 99 | return pow(M_E, ((-_sum) / ( 2.0f * _rbfSigma * _rbfSigma ))); 100 | } 101 | 102 | // 距離概念是越小越近,歸屬度概念是越大越近 ( 或取其差值,使歸屬度同距離越小越近 ) 103 | - (double)distanceBetweenX1:(NSArray *)_x1 x2:(NSArray *)_x2 104 | { 105 | double _distance = 0.0f; 106 | if( nil != _x1 && nil != _x2 ) 107 | { 108 | switch (_kernel) 109 | { 110 | case KRKmeansKernelCosine: 111 | _distance = 1.0f - [self cosineSimilarityX1:_x1 x2:_x2]; 112 | break; 113 | case KRKmeansKernelEuclidean: 114 | _distance = [self euclideanX1:_x1 x2:_x2]; 115 | break; 116 | case KRKmeansKernelRBF: 117 | _distance = [self rbf:_x1 x2:_x2 sigma:_sigma]; 118 | break; 119 | default: 120 | break; 121 | } 122 | } 123 | return _distance; 124 | } 125 | 126 | - (NSInteger)randomIntegerWithMax:(NSInteger)_maxValue min:(NSInteger)_minValue 127 | { 128 | return ( arc4random() / ( RAND_MAX * 2.0f ) ) * (_maxValue - _minValue) + _minValue;; 129 | } 130 | 131 | #pragma --mark NSCoding 132 | -(void)encodeWithCoder:(NSCoder *)aCoder 133 | { 134 | self.coder = aCoder; 135 | [self encodeObject:@(_kernel) forKey:@"kernel"]; 136 | [self encodeObject:@(_sigma) forKey:@"sigma"]; 137 | } 138 | 139 | -(instancetype)initWithCoder:(NSCoder *)aDecoder 140 | { 141 | self = [super init]; 142 | if(self) 143 | { 144 | self.coder = aDecoder; 145 | _kernel = [[self decodeForKey:@"kernel"] integerValue]; 146 | _sigma = [[self decodeForKey:@"sigma"] doubleValue]; 147 | } 148 | return self; 149 | } 150 | 151 | 152 | @end 153 | -------------------------------------------------------------------------------- /ML/KRKmeansOne/KRKmeansOne.h: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeans V2.4.1.h 3 | // KRKmeans V2.4.1 4 | // 5 | // Created by Kalvar on 2014/6/29. 6 | // Copyright (c) 2014 - 2015年 Kalvar Lin, ilovekalvar@gmail.com. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /* 12 | * @ 計算 1 維 K-Means 並分為 3 群 13 | * - Max : 最大數群 14 | * - Min : 最小數群 15 | * - Mid : 中位數群 16 | */ 17 | typedef void(^KRKmeansOneCompletion)(BOOL success, float knowledgeLine, NSArray *maxClusters, NSArray *minClusters, NSArray *midClusters, NSDictionary *overlappings); 18 | 19 | @interface KRKmeansOne : NSObject 20 | 21 | @property (nonatomic, strong) NSArray *sources; 22 | //知識界線 23 | @property (nonatomic, assign) float knowledgeLine; 24 | //最大數群 25 | @property (nonatomic, strong) NSMutableArray *maxClusters; 26 | //最小數群 27 | @property (nonatomic, strong) NSMutableArray *minClusters; 28 | //中位數群 29 | @property (nonatomic, strong) NSMutableArray *midClusters; 30 | //重複出現的數值 31 | @property (nonatomic, strong) NSMutableDictionary *overlappings; 32 | //自訂中位數 33 | @property (nonatomic, assign) float customMedian; 34 | 35 | +(instancetype)sharedKmeans; 36 | -(instancetype)init; 37 | -(void)clusteringWithCompletion:(KRKmeansOneCompletion)_completion; 38 | -(void)clustering; 39 | -(void)printResults; 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /ML/KRKmeansOne/KRKmeansOne.m: -------------------------------------------------------------------------------- 1 | // 2 | // KRKmeans V2.4.1.m 3 | // KRKmeans V2.4.1 4 | // 5 | // Created by Kalvar on 2014/6/29. 6 | // Copyright (c) 2014 - 2015年 Kalvar Lin, ilovekalvar@gmail.com. All rights reserved. 7 | // 8 | 9 | #import "KRKmeansOne.h" 10 | #import "NSArray+Statistics.h" 11 | 12 | @interface KRKmeansOne () 13 | 14 | //是否使用自訂的中位數 15 | @property (nonatomic, assign) BOOL useCustomMedian; 16 | 17 | @end 18 | 19 | @implementation KRKmeansOne 20 | 21 | +(instancetype)sharedKmeans 22 | { 23 | static dispatch_once_t pred; 24 | static KRKmeansOne *_object = nil; 25 | dispatch_once(&pred, ^ 26 | { 27 | _object = [[KRKmeansOne alloc] init]; 28 | }); 29 | return _object; 30 | } 31 | 32 | -(instancetype)init 33 | { 34 | self = [super init]; 35 | if( self ) 36 | { 37 | _sources = nil; 38 | _knowledgeLine = 0.0f; 39 | _maxClusters = nil; 40 | _minClusters = nil; 41 | _midClusters = nil; 42 | _overlappings = nil; 43 | _customMedian = 0.0f; 44 | _useCustomMedian = NO; 45 | } 46 | return self; 47 | } 48 | 49 | /* 50 | * @ 1 維 K-Means 51 | * - One dimensional K-Means 52 | */ 53 | -(void)clusteringWithCompletion:(KRKmeansOneCompletion)_completion 54 | { 55 | //找出陣列裡最大值 56 | float _maxValue = [_sources maximum]; 57 | //找出陣列裡最小值 58 | float _minValue = [_sources minimum]; 59 | //中位數 = 不使用自訂值 ? 用程式找出中位數 : 自訂值; 60 | float _midValue = ( !_useCustomMedian ) ? [_sources median] : _customMedian; 61 | //存放重疊的數值( 重複出現的最大值、最小值、中位數 ), Key = 重疊的 Index 位置,Value = 重疊的值 62 | if( !_overlappings ) 63 | { 64 | _overlappings = [NSMutableDictionary new]; 65 | } 66 | [_overlappings removeAllObjects]; 67 | 68 | if( !_maxClusters ) 69 | { 70 | _maxClusters = [NSMutableArray new]; 71 | } 72 | [_maxClusters removeAllObjects]; 73 | [_maxClusters addObject:[NSNumber numberWithFloat:_maxValue]]; 74 | 75 | if( !_minClusters ) 76 | { 77 | _minClusters = [NSMutableArray new]; 78 | } 79 | [_minClusters removeAllObjects]; 80 | [_minClusters addObject:[NSNumber numberWithFloat:_minValue]]; 81 | 82 | if( !_midClusters ) 83 | { 84 | _midClusters = [NSMutableArray new]; 85 | } 86 | [_midClusters removeAllObjects]; 87 | [_midClusters addObject:[NSNumber numberWithFloat:_midValue]]; 88 | 89 | NSUInteger _index = 0; 90 | NSUInteger _overlappingIndex = 0; 91 | for( NSNumber *_everyNumber in _sources ) 92 | { 93 | //Max 群聚的平均值 94 | float _averageMax = [_maxClusters average]; 95 | //Min 群聚的平均值 96 | float _averageMin = [_minClusters average]; 97 | //Mid 群聚的平均值 98 | float _averageMid = [_midClusters average]; 99 | 100 | float _someValue = _everyNumber.floatValue; 101 | 102 | //計算與各群聚相差的絕對值( 求出距離差異 ) 103 | float _absMax = fabsf(_someValue - _averageMax); 104 | float _absMin = fabsf(_someValue - _averageMin); 105 | float _absMid = fabsf(_someValue - _averageMid); 106 | 107 | //準備將距離越相近的數值放在一起 108 | //如果為 0 就代表已經在同一群裡了 109 | if( _maxValue - _someValue == 0 || _minValue - _someValue == 0 || _midValue - _someValue == 0 ) 110 | { 111 | //記錄重複出現的最大值、最小值、中位數 112 | _overlappingIndex += _index; 113 | [_overlappings setObject:[_everyNumber copy] forKey:[NSNumber numberWithUnsignedInteger:_overlappingIndex]]; 114 | //後續動作不做 115 | //... 116 | } 117 | //判斷目前 _someValue 之距離最接近最大數的群聚 118 | else if( _absMax < _absMin && _absMax < _absMid ) 119 | { 120 | //放入至最大值群聚裡 121 | [_maxClusters addObject:[_everyNumber copy]]; 122 | } 123 | //判斷目前 _someValue 之距離最最接近最小數的群聚 124 | else if ( _absMin < _absMax && _absMin < _absMid ) 125 | { 126 | //放入至最小值群聚裡 127 | [_minClusters addObject:[_everyNumber copy]]; 128 | } 129 | //判斷目前 _someValue 之距離最接近中位數的群聚 130 | else if( _absMid < _absMax && _absMid < _absMin ) 131 | { 132 | [_midClusters addObject:[_everyNumber copy]]; 133 | } 134 | else 135 | { 136 | //如果值都相等,就放入中位數群聚裡 137 | [_midClusters addObject:[_everyNumber copy]]; 138 | } 139 | 140 | ++_index; 141 | } 142 | 143 | _knowledgeLine = ([_maxClusters maximum] + [_minClusters minimum] + [_midClusters median]) / 3; 144 | 145 | if( _completion ) 146 | { 147 | _completion(YES, _knowledgeLine, _maxClusters, _minClusters, _midClusters, _overlappings); 148 | } 149 | } 150 | 151 | -(void)clustering 152 | { 153 | [self clusteringWithCompletion:nil]; 154 | } 155 | 156 | -(void)printResults 157 | { 158 | NSLog(@"knowledgeLine : %f", _knowledgeLine); 159 | NSLog(@"maxClusters : %@", _maxClusters); 160 | NSLog(@"minClusters : %@", _minClusters); 161 | NSLog(@"midClusters : %@", _midClusters); 162 | NSLog(@"overlappings : %@", _overlappings); 163 | } 164 | 165 | #pragma --mark Setters 166 | -(void)setCustomMedian:(float)_median 167 | { 168 | _useCustomMedian = YES; 169 | _customMedian = _median; 170 | } 171 | 172 | @end 173 | 174 | -------------------------------------------------------------------------------- /ML/KRKmeansOne/NSArray+Statistics.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+Statistics.h 3 | // KRKmeans V2.4.1 4 | // 5 | // Created by Kalvar on 2014/6/29. 6 | // Copyright (c) 2014 - 2015年 Kalvar Lin, ilovekalvar@gmail.com. All rights reserved. 7 | // 8 | 9 | @interface NSArray(extensionStatistics) 10 | 11 | -(float)median; 12 | -(float)maximum; 13 | -(float)minimum; 14 | -(float)sum; 15 | -(float)average; 16 | 17 | @end 18 | 19 | @implementation NSArray(extensionStatistics) 20 | 21 | //求中位數 22 | -(float)median 23 | { 24 | return [[[self sortedArrayUsingSelector:@selector(compare:)] objectAtIndex:[self count]/2] floatValue]; 25 | } 26 | 27 | //求最大數 28 | -(float)maximum 29 | { 30 | float xmax = [[self firstObject] floatValue]; 31 | //float xmax = -MAXFLOAT; 32 | //float xmin = MAXFLOAT; 33 | for (NSNumber *num in self) 34 | { 35 | float x = num.floatValue; 36 | //if (x < xmin) xmin = x; 37 | if (x > xmax) 38 | { 39 | xmax = x; 40 | } 41 | } 42 | return xmax; 43 | } 44 | 45 | //求最小數 46 | -(float)minimum 47 | { 48 | float xmin = [[self firstObject] floatValue]; 49 | //float xmax = -MAXFLOAT; 50 | //float xmin = MAXFLOAT; 51 | for (NSNumber *num in self) 52 | { 53 | float x = num.floatValue; 54 | if (x < xmin) xmin = x; 55 | //if (x > xmax) xmax = x; 56 | } 57 | return xmin; 58 | } 59 | 60 | -(float)sum 61 | { 62 | float _sum = 0.0f; 63 | for( NSNumber *_number in self ) 64 | { 65 | _sum += [_number floatValue]; 66 | } 67 | return _sum; 68 | } 69 | 70 | -(float)average 71 | { 72 | return ( [self sum] / [self count] ); 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /ML/KRKmeansSaver/KRKmeansSaver.h: -------------------------------------------------------------------------------- 1 | // 2 | // KRFuzzySaves.h 3 | // KRFuzzyCMeans 4 | // 5 | // Created by Kalvar Lin on 2015/11/15. 6 | // Copyright © 2015年 Kalvar. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class KRKmeansGroup; 12 | 13 | @interface KRKmeansSaver : NSObject 14 | 15 | + (instancetype)sharedSaver; 16 | - (instancetype)init; 17 | 18 | - (void)save:(NSMutableArray *)object forKey:(NSString *)key; 19 | - (void)removeForKey:(NSString *)key; 20 | - (NSMutableArray *)objectForKey:(NSString *)key; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /ML/KRKmeansSaver/KRKmeansSaver.m: -------------------------------------------------------------------------------- 1 | // 2 | // KRFuzzySaves.h 3 | // KRFuzzyCMeans 4 | // 5 | // Created by Kalvar Lin on 2015/11/15. 6 | // Copyright © 2015年 Kalvar. All rights reserved. 7 | // 8 | 9 | #import "KRKmeansSaver.h" 10 | #import "KRKmeansGroup.h" 11 | 12 | static NSString *kKRKmeansSavesCentersKey = @"kKRKmeansSavesCentersKey"; 13 | 14 | @implementation KRKmeansSaver 15 | 16 | + (instancetype)sharedSaver 17 | { 18 | static dispatch_once_t pred; 19 | static KRKmeansSaver *_object = nil; 20 | dispatch_once(&pred, ^{ 21 | _object = [[KRKmeansSaver alloc] init]; 22 | }); 23 | return _object; 24 | } 25 | 26 | - (instancetype)init 27 | { 28 | self = [super init]; 29 | if( self ) 30 | { 31 | 32 | } 33 | return self; 34 | } 35 | 36 | - (void)save:(NSMutableArray *)object forKey:(NSString *)key 37 | { 38 | if( object && key ) 39 | { 40 | [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:object] forKey:key]; 41 | [[NSUserDefaults standardUserDefaults] synchronize]; 42 | } 43 | } 44 | 45 | - (void)removeForKey:(NSString *)key 46 | { 47 | if( key ) 48 | { 49 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:key]; 50 | [[NSUserDefaults standardUserDefaults] synchronize]; 51 | } 52 | } 53 | 54 | - (NSMutableArray *)objectForKey:(NSString *)key 55 | { 56 | if( key ) 57 | { 58 | NSData *_objectData = [[NSUserDefaults standardUserDefaults] valueForKey:key]; 59 | return _objectData ? [NSKeyedUnarchiver unarchiveObjectWithData:_objectData] : nil; 60 | } 61 | return nil; 62 | } 63 | 64 | @end -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ios-KRKmeans-Algorithm 2 | ================= 3 | 4 | KRKmeans has implemented K-Means the clustering algorithm (クラスタリング分類) and achieved multi-dimensional clustering in this project. KRKmeans could be used in data mining (データマイニング), image compression (画像圧縮) and classification. 5 | 6 | #### Podfile 7 | 8 | ```ruby 9 | platform :ios, '7.0' 10 | pod "KRKmeans", "~> 2.6.1" 11 | ``` 12 | 13 | ## How to use 14 | 15 | #### Imports 16 | 17 | ``` objective-c 18 | #import "KRKmeans.h" 19 | ``` 20 | 21 | #### Distance Methods 22 | 23 | ``` objective-c 24 | "KRKmeansKernelCosine" is Cosine Similarity. 25 | "KRKmeansKernelEuclidean" is Euclidean. 26 | "KRKmeansKernelRBF" is Radial Basis Function. 27 | ``` 28 | 29 | #### Choosing Centers of Groups 30 | 31 | ``` objective-c 32 | // 1. Random choosing the centers of groups from patterns. 33 | [kmeans randomChooseCenters:3]; 34 | 35 | // 2. Quickly customizing the groups and centers 36 | [kmeans addGroupForCenterFeatures:@[@2, @2] centerId:@"Center_1" groupId:@"Group_1"]; 37 | [kmeans addGroupForCenterFeatures:@[@6, @5] centerId:@"Center_2" groupId:@"Group_2"]; 38 | [kmeans addGroupForCenterFeatures:@[@3, @17] centerId:@"Center_3" groupId:@"Group_3"]; 39 | ``` 40 | 41 | #### One dimensonal clustering 42 | 43 | The one dimensonal clustering. 44 | 45 | ``` objective-c 46 | -(void)oneDemensionalClustering 47 | { 48 | //One dimensional K-Means, the data set is any number means. 49 | KRKmeansOne *kmeansOne = [KRKmeansOne sharedKmeans]; 50 | kmeansOne.sources = @[@0.33, @0.88, @1, @0.52, @146, @120, @45, @43, @0.4]; 51 | 52 | //If you wanna customize the median value 53 | //kmeansOne.customMedian = 45.0f; 54 | 55 | [kmeansOne clusteringWithCompletion:^(BOOL success, float knowledgeLine, NSArray *maxClusters, NSArray *minClusters, NSArray *midClusters, NSDictionary *overlappings) 56 | { 57 | NSLog(@"knowledgeLine : %f", knowledgeLine); 58 | NSLog(@"maxClusters : %@", maxClusters); 59 | NSLog(@"minClusters : %@", minClusters); 60 | NSLog(@"midClusters : %@", midClusters); 61 | NSLog(@"overlappings : %@", overlappings); 62 | //[_krKmeansOne printResults]; 63 | }]; 64 | } 65 | 66 | ``` 67 | 68 | #### Multi-dimensonal clustering 69 | 70 | ``` objective-c 71 | -(void)multiClustering 72 | { 73 | KRKmeans *kmeans = [KRKmeans sharedKmeans]; 74 | kmeans.modelKey = @"MyKmeans1"; 75 | kmeans.saveAfterDone = YES; 76 | kmeans.maxIteration = 10; 77 | 78 | // Adding patterns 79 | NSArray *patterns = @[@[@5, @4], @[@3, @4], @[@2, @5], @[@9, @8], @[@3, @20], 80 | @[@1, @1], @[@1, @2], @[@2, @2], @[@3, @2], @[@3, @1], 81 | @[@6, @4], @[@7, @6], @[@5, @6], @[@6, @5], @[@7, @8], 82 | @[@3, @12], @[@5, @20]]; 83 | NSInteger index = -1; 84 | for( NSArray *features in patterns ) 85 | { 86 | index += 1; 87 | NSString *patternId = [NSString stringWithFormat:@"Training_%li", index]; 88 | KRKmeansPattern *pattern = [kmeans createPatternWithFeatures:features patternId:patternId]; 89 | [kmeans addPattern:pattern]; 90 | } 91 | 92 | [kmeans randomChooseCenters:3]; 93 | [kmeans setupKernel:KRKmeansKernelEuclidean]; 94 | [kmeans clusteringWithCompletion:^(BOOL success, KRKmeans *kmeansObject, NSInteger totalTimes) { 95 | NSLog(@"totalTimes : %li", totalTimes); 96 | NSLog(@"featuresOfCenters : %@", kmeansObject.featuresOfCenters); 97 | NSLog(@"centers objects: %@", kmeansObject.centers); 98 | NSLog(@"SSE : %lf", kmeansObject.sse); 99 | } perIteration:^(NSInteger times, KRKmeans *kmeansObject, BOOL *pause) { 100 | NSLog(@"times : %li", times); 101 | // If you want to direct pause that next iteration running, then you could set : 102 | //*pause = YES; 103 | }]; 104 | 105 | } 106 | ``` 107 | 108 | #### Predicating & Recovering 109 | 110 | To recover that trained model to predicate the patterns. 111 | 112 | ``` objective-c 113 | // Recovering the tranined groups to predicate patterns. 114 | -(void)predicatingByTrainedModel 115 | { 116 | KRKmeans *kmeans = [KRKmeans sharedKmeans]; 117 | [kmeans recoverGroupsForKey:@"MyKmeans1"]; 118 | 119 | NSMutableArray *samples = [NSMutableArray new]; 120 | NSArray *patterns = @[@[@21, @12], @[@13, @21], @[@12, @5], @[@3, @8]]; 121 | NSInteger index = -1; 122 | for( NSArray *features in patterns ) 123 | { 124 | index += 1; 125 | NSString *patternId = [NSString stringWithFormat:@"Predication_%li", index]; 126 | KRKmeansPattern *pattern = [kmeans createPatternWithFeatures:features patternId:patternId]; 127 | [samples addObject:pattern]; 128 | } 129 | 130 | [kmeans predicatePatterns:samples completion:^(BOOL success, KRKmeans *kmeansObject, NSInteger totalTimes) { 131 | NSLog(@"\n\n====================== Predication ===========================\n\n"); 132 | [kmeansObject printResults]; 133 | }]; 134 | 135 | } 136 | ``` 137 | 138 | ## Version 139 | 140 | V2.6.1 141 | 142 | ## License 143 | 144 | MIT. --------------------------------------------------------------------------------