Skip to content

Commit 160ba2c

Browse files
committed
Updated V1.3
Added methods to save trained centers.
1 parent f47397a commit 160ba2c

File tree

8 files changed

+212
-75
lines changed

8 files changed

+212
-75
lines changed

FCM/KRFuzzyCMeans.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ typedef void(^KRFuzzyCMeansPerIteration)(NSInteger times, NSArray *clusters, NSA
4747
@property (nonatomic, assign) NSInteger maxIteration;
4848
//FCM 公式 m 參數
4949
@property (nonatomic, assign) NSInteger m;
50+
//訓練完是否自動儲存
51+
@property (nonatomic, assign) BOOL doneThenSave;
5052

5153
@property (nonatomic, assign) KRFuzzyCMeansDistanceFormula distanceFormula;
5254

@@ -55,12 +57,16 @@ typedef void(^KRFuzzyCMeansPerIteration)(NSInteger times, NSArray *clusters, NSA
5557

5658
+(instancetype)sharedFCM;
5759
-(instancetype)init;
60+
5861
-(void)clusterWithCompletion:(KRFuzzyCMeansClusteringCompletion)_completion perIteration:(KRFuzzyCMeansPerIteration)_generation;
5962
-(void)clusterWithCompletion:(KRFuzzyCMeansClusteringCompletion)_completion;
6063
-(void)cluster;
6164
-(void)directClusterPatterns:(NSArray *)_directPatterns;
62-
-(void)addCentralX:(float)_x y:(float)_y;
65+
66+
-(void)addCenters:(NSArray *)_theCenters;
6367
-(void)addPatterns:(NSArray *)_theSets;
68+
69+
-(void)recallCenters;
6470
-(void)printResults;
6571

6672
#pragma --mark Blocks

FCM/KRFuzzyCMeans.m

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77
//
88

99
#import "KRFuzzyCMeans.h"
10+
#import "KRFuzzyCMeansSaves.h"
1011

1112
@interface KRFuzzyCMeans()
1213

1314
//上一次運算的群聚中心點集合
1415
@property (nonatomic, strong) NSMutableArray *lastCenters;
1516
//當前的迭代數
1617
@property (nonatomic, assign) NSInteger currentIteration;
18+
//儲存訓練好的群心和其它數據
19+
@property (nonatomic, strong) KRFuzzyCMeansSaves *trainedSaves;
1720

1821
@end
1922

@@ -75,21 +78,40 @@ -(float)_distanceX1:(NSArray *)_x1 x2:(NSArray *)_x2
7578

7679
@end
7780

81+
@implementation KRFuzzyCMeans(fixSaves)
82+
83+
-(void)_saveCenters
84+
{
85+
[self.trainedSaves saveCenters:self.centrals];
86+
}
87+
88+
-(NSArray *)_fetchSavedCenters
89+
{
90+
return [self.trainedSaves fetchCenters];
91+
}
92+
93+
@end
94+
7895
@implementation KRFuzzyCMeans(fixClusters)
7996

8097
-(void)_doneClustering
8198
{
99+
if( self.doneThenSave )
100+
{
101+
[self _saveCenters];
102+
}
103+
82104
if( self.clusterCompletion )
83105
{
84106
self.clusterCompletion(YES, self.results, self.centrals, self.currentIteration);
85107
}
86108
}
87109

88-
//更新群聚形心
110+
// 更新群聚形心
89111
-(NSArray *)_updateCenters:(NSArray *)_centers memberships:(NSArray *)_xMembersips patterns:(NSArray *)_sources
90112
{
91113
/*
92-
* @ Design thinks
114+
* @ Design thinks before
93115
* - 如果在上面的 for{} 區塊進行歸屬度累加計算,就必須同時考量存取 N 個 Array ( 裡面儲存對每一個形心做 SUM 的數值 ) 的效能,
94116
* 同時重複存取 Array 的次數越多,其 performance 就越差,會遠比使用單一 for{} 來重複做事要更沒效能,
95117
* 因此,這裡才改用單一 for{} 來做多重存取,以避免重複操作太多 arraies 造成效能大降的問題,
@@ -145,8 +167,8 @@ -(NSArray *)_updateCenters:(NSArray *)_centers memberships:(NSArray *)_xMembersi
145167
return _newCentrals;
146168
}
147169

148-
//進行 Patterns 分類和歸屬度運算
149-
//return [0] = 分類好的群聚, [1] = 每一個 Pattern 對每一群心的歸屬度
170+
// 進行 Patterns 分類和歸屬度運算
171+
// return [0] = 分類好的群聚, [1] = 每一個 Pattern 對每一群心的歸屬度
150172
-(NSArray *)_clusteringPatterns:(NSArray *)_sources centers:(NSArray *)_centers
151173
{
152174
float _m = self.m;
@@ -221,7 +243,7 @@ -(NSArray *)_clusteringPatterns:(NSArray *)_sources centers:(NSArray *)_centers
221243
return @[_clusters, _xMembersips];
222244
}
223245

224-
//取出跟上一次舊的群聚形心相比的最大誤差值
246+
// 取出跟上一次舊的群聚形心相比的最大誤差值
225247
-(float)_calculateErrorDistanceFromNewCenters:(NSArray *)_newCenters oldCenters:(NSArray *)_oldCenters
226248
{
227249
float _maxDistance = 0.0f;
@@ -243,9 +265,7 @@ -(float)_calculateErrorDistanceFromNewCenters:(NSArray *)_newCenters oldCenters:
243265
return _maxDistance;
244266
}
245267

246-
/*
247-
* @ 依照群聚中心點(形心) _centers 進行 _sources 群聚分類
248-
*/
268+
// 依照群聚中心點(形心) _centers 進行 _sources 群聚分類
249269
-(void)_clusterSources:(NSArray *)_sources compareCenters:(NSArray *)_centers
250270
{
251271
if( [_centers count] > 0 )
@@ -254,7 +274,6 @@ -(void)_clusterSources:(NSArray *)_sources compareCenters:(NSArray *)_centers
254274
{
255275
self.m = 2;
256276
}
257-
258277
NSArray *_results = [self _clusteringPatterns:_sources centers:_centers];
259278
NSArray *_clusters = [_results objectAtIndex:0];
260279
NSArray *_membersips = [_results objectAtIndex:1];
@@ -294,25 +313,11 @@ -(void)_clusterSources:(NSArray *)_sources compareCenters:(NSArray *)_centers
294313

295314
@implementation KRFuzzyCMeans
296315

297-
@synthesize centrals = _centrals;
298-
@synthesize patterns = _patterns;
299-
@synthesize results = _results;
300-
@synthesize convergenceError = _convergenceError;
301-
@synthesize maxIteration = _maxIteration;
302-
@synthesize m = _m;
303-
304-
@synthesize clusterCompletion = _clusterCompletion;
305-
@synthesize perIteration = _perIteration;
306-
307-
@synthesize lastCenters = _lastCenters;
308-
@synthesize currentIteration = _currentIteration;
309-
310316
+(instancetype)sharedFCM
311317
{
312318
static dispatch_once_t pred;
313319
static KRFuzzyCMeans *_object = nil;
314-
dispatch_once(&pred, ^
315-
{
320+
dispatch_once(&pred, ^{
316321
_object = [[KRFuzzyCMeans alloc] init];
317322
});
318323
return _object;
@@ -329,6 +334,7 @@ -(instancetype)init
329334
_convergenceError = 0.001f;
330335
_maxIteration = 5000;
331336
_m = 2;
337+
_doneThenSave = YES;
332338

333339
_clusterCompletion = nil;
334340
_perIteration = nil;
@@ -337,6 +343,7 @@ -(instancetype)init
337343
_currentIteration = 0;
338344

339345
_distanceFormula = KRFuzzyCMeansDistanceFormulaByEuclidean;
346+
_trainedSaves = [KRFuzzyCMeansSaves sharedInstance];
340347
}
341348
return self;
342349
}
@@ -406,7 +413,7 @@ -(void)clusterWithCompletion:(KRFuzzyCMeansClusteringCompletion)_completion perI
406413
{
407414
_clusterCompletion = _completion;
408415
_perIteration = _generation;
409-
_currentIteration = 0;
416+
_currentIteration = 0;
410417
[self _clusterSources:_patterns compareCenters:_centrals];
411418
}
412419

@@ -420,16 +427,27 @@ -(void)cluster
420427
[self clusterWithCompletion:nil];
421428
}
422429

423-
-(void)addCentralX:(float)_x y:(float)_y
430+
-(void)addCenters:(NSArray *)_theCenters
424431
{
425-
[_centrals addObject:@[[NSNumber numberWithFloat:_x], [NSNumber numberWithFloat:_y]]];
432+
[_centrals addObject:_theCenters];
426433
}
427434

428435
-(void)addPatterns:(NSArray *)_theSets
429436
{
430437
[_patterns addObjectsFromArray:_theSets];
431438
}
432439

440+
// Recalling trained centers which saved in KRFuzzyCMeansSaves
441+
-(void)recallCenters
442+
{
443+
NSArray *_savedCenters = [self _fetchSavedCenters];
444+
if( nil != _savedCenters )
445+
{
446+
[_centrals removeAllObjects];
447+
[_centrals addObjectsFromArray:_savedCenters];
448+
}
449+
}
450+
433451
-(void)printResults
434452
{
435453
NSLog(@"=================== printResults (Start) =================\n\n\n");
@@ -452,7 +470,7 @@ -(void)setClusterCompletion:(KRFuzzyCMeansClusteringCompletion)_theBlock
452470

453471
-(void)setPerIteration:(KRFuzzyCMeansPerIteration)_theBlock
454472
{
455-
_perIteration = _theBlock;
473+
_perIteration = _theBlock;
456474
}
457475

458476
@end

FCM/KRFuzzyCMeansSaves.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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 <Foundation/Foundation.h>
10+
11+
@interface KRFuzzyCMeansSaves : NSObject
12+
13+
+(instancetype)sharedInstance;
14+
-(instancetype)init;
15+
16+
-(void)saveCenters:(NSArray *)_centers;
17+
-(NSArray *)fetchCenters;
18+
-(void)deleteCenters;
19+
20+
@end

FCM/KRFuzzyCMeansSaves.m

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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 "KRFuzzyCMeansSaves.h"
10+
11+
static NSString *kKRFuzzyCMeansSavesCentersKey = @"kKRFuzzyCMeansSavesCentersKey";
12+
13+
@implementation KRFuzzyCMeansSaves (fixSaves)
14+
15+
-(NSUserDefaults *)_userDefaults
16+
{
17+
return [NSUserDefaults standardUserDefaults];
18+
}
19+
20+
-(void)_synchronize
21+
{
22+
[[self _userDefaults] synchronize];
23+
}
24+
25+
-(instancetype)_defaultValueForKey:(NSString *)_key
26+
{
27+
return [[self _userDefaults] objectForKey:_key];
28+
}
29+
30+
-(void)_saveDefaultValue:(NSArray *)_value forKey:(NSString *)_forKey
31+
{
32+
[[self _userDefaults] setObject:_value forKey:_forKey];
33+
[self _synchronize];
34+
}
35+
36+
-(void)_removeValueForKey:(NSString *)_key
37+
{
38+
[[self _userDefaults] removeObjectForKey:_key];
39+
[self _synchronize];
40+
}
41+
42+
@end
43+
44+
@implementation KRFuzzyCMeansSaves
45+
46+
+(instancetype)sharedInstance
47+
{
48+
static dispatch_once_t pred;
49+
static KRFuzzyCMeansSaves *_object = nil;
50+
dispatch_once(&pred, ^{
51+
_object = [[KRFuzzyCMeansSaves alloc] init];
52+
});
53+
return _object;
54+
}
55+
56+
-(instancetype)init
57+
{
58+
self = [super init];
59+
if( self )
60+
{
61+
62+
}
63+
return self;
64+
}
65+
66+
-(void)saveCenters:(NSArray *)_centers
67+
{
68+
[self _saveDefaultValue:[_centers copy] forKey:kKRFuzzyCMeansSavesCentersKey];
69+
}
70+
71+
-(NSArray *)fetchCenters
72+
{
73+
return (NSArray *)[self _defaultValueForKey:kKRFuzzyCMeansSavesCentersKey];
74+
}
75+
76+
-(void)deleteCenters
77+
{
78+
[self _removeValueForKey:kKRFuzzyCMeansSavesCentersKey];
79+
}
80+
81+
@end

KRFuzzyCMeans.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "KRFuzzyCMeans"
3-
s.version = "1.2"
3+
s.version = "1.3"
44
s.summary = "Fuzzy C-Means is clustering algorithm combined fuzzy theory on Machine Learning."
55
s.description = <<-DESC
66
KRFuzzyCMeans has implemented Fuzzy C-Means (FCM) the fuzzy (ファジー理論) clustering / classification algorithm (クラスタリング分類) in Machine Learning (マシンラーニング). It could be used in data mining (データマイニング) and image compression (画像圧縮).

KRFuzzyCMeans.xcodeproj/project.pbxproj

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
8E3F30DA1BF83278004FEC88 /* KRFuzzyCMeansSaves.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E3F30D91BF83278004FEC88 /* KRFuzzyCMeansSaves.m */; settings = {ASSET_TAGS = (); }; };
1011
8E44AE621AD1A26D00A3F154 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E44AE611AD1A26D00A3F154 /* main.m */; };
1112
8E44AE651AD1A26D00A3F154 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E44AE641AD1A26D00A3F154 /* AppDelegate.m */; };
1213
8E44AE681AD1A26D00A3F154 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E44AE671AD1A26D00A3F154 /* ViewController.m */; };
@@ -28,6 +29,8 @@
2829
/* End PBXContainerItemProxy section */
2930

3031
/* Begin PBXFileReference section */
32+
8E3F30D81BF83278004FEC88 /* KRFuzzyCMeansSaves.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KRFuzzyCMeansSaves.h; sourceTree = "<group>"; };
33+
8E3F30D91BF83278004FEC88 /* KRFuzzyCMeansSaves.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KRFuzzyCMeansSaves.m; sourceTree = "<group>"; };
3134
8E44AE5C1AD1A26D00A3F154 /* KRFuzzyCMeans.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KRFuzzyCMeans.app; sourceTree = BUILT_PRODUCTS_DIR; };
3235
8E44AE601AD1A26D00A3F154 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3336
8E44AE611AD1A26D00A3F154 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
@@ -126,6 +129,8 @@
126129
8E6E14E21AFD29FC000F743C /* FCM */ = {
127130
isa = PBXGroup;
128131
children = (
132+
8E3F30D81BF83278004FEC88 /* KRFuzzyCMeansSaves.h */,
133+
8E3F30D91BF83278004FEC88 /* KRFuzzyCMeansSaves.m */,
129134
8E6E14E31AFD29FC000F743C /* KRFuzzyCMeans.h */,
130135
8E6E14E41AFD29FC000F743C /* KRFuzzyCMeans.m */,
131136
);
@@ -235,6 +240,7 @@
235240
8E44AE681AD1A26D00A3F154 /* ViewController.m in Sources */,
236241
8E44AE651AD1A26D00A3F154 /* AppDelegate.m in Sources */,
237242
8E6E14E51AFD29FC000F743C /* KRFuzzyCMeans.m in Sources */,
243+
8E3F30DA1BF83278004FEC88 /* KRFuzzyCMeansSaves.m in Sources */,
238244
8E44AE621AD1A26D00A3F154 /* main.m in Sources */,
239245
);
240246
runOnlyForDeploymentPostprocessing = 0;

0 commit comments

Comments
 (0)