Skip to content

Commit 7ff2f45

Browse files
committed
Updated V1.1.0
1 parent b7539d0 commit 7ff2f45

File tree

6 files changed

+129
-301
lines changed

6 files changed

+129
-301
lines changed

KRHebbian.podspec

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
Pod::Spec.new do |s|
22
s.name = "KRHebbian"
3-
s.version = "1.0.2"
4-
s.summary = "Self learning the adjust weight method on Machine Learning."
3+
s.version = "1.1.0"
4+
s.summary = "Non-supervisor that Hebbian self-organization learning method in machine learning. (自分学習アルゴリズム)."
55
s.description = <<-DESC
6-
KRHebbian is a self-learning algorithm (adjust the weights) in neural network of Machine Learning (自分学習アルゴリズム).
6+
KRHebbian implemented Hebbian algorithm that is a non-supervisor of self-organization algorithm of Machine Learning (自分学習アルゴリズム).
77
DESC
88
s.homepage = "https://github.com/Kalvar/ios-KRHebbian-Algorithm"
99
s.license = { :type => 'MIT', :file => 'LICENSE' }

KRHebbian/KRHebbian.h

+20-18
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,28 @@
88

99
#import <Foundation/Foundation.h>
1010

11+
typedef void(^KRHebbianCompletion)(BOOL success, NSArray *weights, NSInteger totalIteration);
12+
typedef void(^KRHebbianIteration)(NSInteger iteration, NSArray *weights);
13+
1114
@interface KRHebbian : NSObject
12-
{
13-
//學習速率 ( eta )
14-
CGFloat theta;
15-
//初始權重陣列 ( 2 維, 未轉矩 )
16-
NSArray *weights;
17-
//初始參數陣列 ( 1 維 )
18-
NSArray *params;
19-
//運算完成的新權重 ( 1 維 )
20-
NSMutableArray *deltaWeights;
21-
}
22-
23-
@property (nonatomic, assign) CGFloat theta;
24-
@property (nonatomic, strong) NSArray *weights;
25-
@property (nonatomic, strong) NSArray *params;
26-
@property (nonatomic, strong) NSMutableArray *deltaWeights;
15+
16+
@property (nonatomic, strong) NSMutableArray *patterns;
17+
@property (nonatomic, strong) NSMutableArray *weights;
18+
@property (nonatomic, assign) CGFloat learningRate;
19+
@property (nonatomic, assign) NSInteger maxIteration;
20+
21+
@property (nonatomic, copy) KRHebbianCompletion trainingCompletion;
22+
@property (nonatomic, copy) KRHebbianIteration trainingIteraion;
2723

2824
+(instancetype)sharedAlgorithm;
29-
-(NSMutableArray *)transposeMatrix:(NSArray *)_matrix;
30-
-(void)transposeWeights;
31-
-(NSMutableArray *)training;
25+
-(instancetype)init;
26+
27+
-(void)addPatterns:(NSArray *)_inputs;
28+
-(void)initializeWeights:(NSArray *)_initWeights;
29+
-(void)training;
30+
-(void)trainingWithCompletion:(KRHebbianCompletion)_completion;
31+
32+
-(void)setTrainingCompletion:(KRHebbianCompletion)_block;
33+
-(void)setTrainingIteraion:(KRHebbianIteration)_block;
3234

3335
@end

KRHebbian/KRHebbian.m

+71-198
Original file line numberDiff line numberDiff line change
@@ -10,176 +10,63 @@
1010

1111
@interface KRHebbian ()
1212

13-
//轉置後的權重矩陣
14-
@property (nonatomic, strong) NSMutableArray *_transposedWeights;
13+
@property (nonatomic, assign) NSInteger iteration;
1514

1615
@end
1716

18-
@interface KRHebbian (fixPrivate)
19-
20-
-(void)_initWithVars;
21-
22-
@end
23-
24-
@implementation KRHebbian (fixPrivate)
25-
26-
-(void)_initWithVars
27-
{
28-
self.theta = 0.0f;
29-
self.weights = nil;
30-
self.params = nil;
31-
deltaWeights = [[NSMutableArray alloc] initWithCapacity:0];
32-
self._transposedWeights = [NSMutableArray arrayWithCapacity:0];
33-
}
34-
35-
@end
36-
37-
@interface KRHebbian (fixMatrixes)
38-
39-
-(double)sumTransposedMatrix:(NSArray *)_transposedMatrix multiplyMatrix:(NSArray *)_multiplicandMatrix;
40-
-(NSMutableArray *)weightMatrix:(NSArray *)_weightMatrix plusMatrix:(NSArray *)_plusMatrix theMark:(double)_mark;
41-
-(NSInteger)sgn:(double)_sgnValue;
42-
43-
@end
44-
45-
@implementation KRHebbian (fixMatrixes)
46-
/*
47-
* @ 累加( 轉置後的矩陣乘以另一個未轉置矩陣 ) ( 直 1 維 x 橫 1 維 )
48-
*
49-
* - 赫賓是 1 維 x 1 維 ( 不需考慮 N 維 )
50-
*
51-
* - 兩個矩陣必須滿足 A 矩陣的行數等於 B 矩陣的列數才可以相乘
52-
*
53-
* - _multiplierMatrix 乘數 ( 轉置後的矩陣 )
54-
*
55-
* @[ @[1], @[2], @[3] ]
56-
*
57-
* - _multiplicandMatrix 被乘數
58-
*
59-
* @[4, 5, 6]
60-
*
61-
*/
62-
-(double)sumTransposedMatrix:(NSArray *)_transposedMatrix multiplyMatrix:(NSArray *)_multiplicandMatrix
63-
{
64-
NSUInteger _transposedCount = 1; //[_transposedMatrix count];
65-
if( [[_transposedMatrix objectAtIndex:0] isKindOfClass:[NSArray class]] )
66-
{
67-
_transposedCount = [[_transposedMatrix objectAtIndex:0] count];
68-
}
69-
NSUInteger _multiplicandCount = [_multiplicandMatrix count];
70-
double _sum = 0.0f;
71-
//轉置矩陣的長度
72-
for( int i=0; i<_transposedCount; i++ )
73-
{
74-
//被乘矩陣的長度
75-
for( int j=0; j<_multiplicandCount; j++ )
76-
{
77-
//NSLog(@"i = %i, j = %i", i, j);
78-
//避免 Exception for Crash
79-
if( j > _transposedCount )
80-
{
81-
break;
82-
}
83-
double _transposedValue = [[[_transposedMatrix objectAtIndex:j] objectAtIndex:i] doubleValue];
84-
double _multiplicandValue = [[_multiplicandMatrix objectAtIndex:j] doubleValue];
85-
//NSLog(@"_transposedValue : %f", _transposedValue);
86-
//NSLog(@"_multiplicandValue : %f\n\n", _multiplicandValue);
87-
_sum += _transposedValue * _multiplicandValue;
88-
}
89-
}
90-
return _sum;
91-
}
92-
93-
/*
94-
* @ 權重矩陣相加(矩陣一, 矩陣二, 標記)
95-
*/
96-
-(NSMutableArray *)weightMatrix:(NSArray *)_weightMatrix plusMatrix:(NSArray *)_plusMatrix theMark:(double)_mark
97-
{
98-
NSMutableArray *_sums = [NSMutableArray arrayWithCapacity:0];
99-
NSUInteger _weightCount = [_weightMatrix count];
100-
if( _weightCount < [_plusMatrix count] )
101-
{
102-
//代表 _weightMatrix 為多維陣列
103-
_weightCount = [[_weightMatrix objectAtIndex:0] count];
104-
}
105-
106-
if( _mark > 0 )
107-
{
108-
for( int i=0; i<_weightCount; i++ )
109-
{
110-
double _weightValue = [[[_weightMatrix objectAtIndex:0] objectAtIndex:i] doubleValue];
111-
double _matrixValue = [[_plusMatrix objectAtIndex:i] doubleValue];
112-
[_sums addObject:[NSString stringWithFormat:@"%lf", ( _weightValue + _matrixValue )]];
113-
}
114-
}
115-
116-
if( _mark < 0 )
117-
{
118-
for( int i=0; i<_weightCount; i++ )
119-
{
120-
double _weightValue = [[[_weightMatrix objectAtIndex:0] objectAtIndex:i] doubleValue];
121-
double _matrixValue = [[_plusMatrix objectAtIndex:i] doubleValue];
122-
[_sums addObject:[NSString stringWithFormat:@"%lf", ( _weightValue - _matrixValue )]];
123-
}
124-
}
125-
126-
return _sums;
127-
}
128-
17+
@implementation KRHebbian (fixNets)
12918
/*
13019
* @ 求 SGN()
13120
*/
132-
-(NSInteger)sgn:(double)_sgnValue
21+
-(NSInteger)_sgn:(double)_sgnValue
13322
{
134-
return ( _sgnValue >= 0 ) ? 1 : -1;
23+
return ( _sgnValue >= 0.0f ) ? 1 : -1;
13524
}
13625

137-
@end
138-
139-
@interface KRHebbian (fixNets)
140-
141-
-(NSInteger)_findFOfNet;
142-
-(NSMutableArray *)_findNextDeltaWeightsWithFOfNet:(NSInteger)_fOfNet;
143-
144-
@end
145-
146-
@implementation KRHebbian (fixNets)
14726
/*
14827
* @ Step 1. 求出 Net
14928
* @ Step 2. 求出 sgn()
15029
*
15130
* @ 回傳 sgn()
15231
*
15332
*/
154-
-(NSInteger)_findFOfNet
33+
-(NSInteger)_fOfNetWithInputs:(NSArray *)_inputs
15534
{
156-
//W1 & X1
157-
double _net = [self sumTransposedMatrix:self._transposedWeights multiplyMatrix:self.params];
158-
//回傳 sgn() 判定值
159-
return [self sgn:_net];
35+
double _sum = 0.0f;
36+
NSInteger _index = 0;
37+
for( NSNumber *_xValue in _inputs )
38+
{
39+
_sum += [_xValue floatValue] * [[self.weights objectAtIndex:_index] floatValue];
40+
++_index;
41+
}
42+
return [self _sgn:_sum];
16043
}
16144

16245
/*
16346
* @ Step 3. 求 delta W (下一節點之權重值)
16447
*/
165-
-(NSMutableArray *)_findNextDeltaWeightsWithFOfNet:(NSInteger)_fOfNet
48+
-(void)_turningWeightsByInputs:(NSArray *)_inputs
16649
{
167-
double _mark = self.theta * _fOfNet;
168-
//這裡要用初始的權重矩陣
169-
return [self weightMatrix:self.weights
170-
plusMatrix:self.params
171-
theMark:_mark];
50+
NSArray *_weights = self.weights;
51+
float _learningRate = self.learningRate;
52+
float _netOutput = [self _fOfNetWithInputs:_inputs];
53+
NSMutableArray *_newWeights = [NSMutableArray new];
54+
NSInteger _index = 0;
55+
for( NSNumber *_weightValue in _weights )
56+
{
57+
float _deltaWeight = ( _learningRate * _netOutput * [[_inputs objectAtIndex:_index] floatValue] );
58+
float _newWeight = [_weightValue floatValue] + _deltaWeight;
59+
[_newWeights addObject:[NSNumber numberWithFloat:_newWeight]];
60+
++_index;
61+
}
62+
[self.weights removeAllObjects];
63+
[self.weights addObjectsFromArray:_newWeights];
17264
}
17365

17466
@end
17567

17668
@implementation KRHebbian
17769

178-
@synthesize theta = _theta;
179-
@synthesize weights = _weights;
180-
@synthesize params = _params;
181-
@synthesize deltaWeights = _deltaWeights;
182-
18370
+(instancetype)sharedAlgorithm
18471
{
18572
static dispatch_once_t pred;
@@ -190,90 +77,76 @@ +(instancetype)sharedAlgorithm
19077
return _object;
19178
}
19279

193-
-(id)init
80+
-(instancetype)init
19481
{
19582
self = [super init];
19683
if( self )
19784
{
198-
[self _initWithVars];
85+
_learningRate = 0.5f;
86+
_weights = [NSMutableArray new];
87+
_patterns = [NSMutableArray new];
88+
89+
_iteration = 0;
90+
_maxIteration = 1;
19991
}
20092
return self;
20193
}
20294

203-
#pragma --mark Public Matrix Methods
204-
/*
205-
* @ 轉置矩陣
206-
* - 1. 傳入 1 維陣列
207-
* - 2. 傳入 2 維陣列
208-
* - 3. 傳入 N 維陣列
209-
*/
210-
-(NSMutableArray *)transposeMatrix:(NSArray *)_matrix
95+
#pragma --mark Public Hebbian Algorithm
96+
-(void)addPatterns:(NSArray *)_inputs
97+
{
98+
[_patterns addObject:_inputs];
99+
}
100+
101+
-(void)initializeWeights:(NSArray *)_initWeights
102+
{
103+
if( [_weights count] > 0 )
104+
{
105+
[_weights removeAllObjects];
106+
}
107+
[_weights addObjectsFromArray:_initWeights];
108+
}
109+
110+
-(void)training
211111
{
212-
/*
213-
* @ 多維陣列要用多個 Array 互包來完成
214-
*/
215-
if( !_matrix ) return nil;
216-
NSMutableArray *_transposedMatrix = [[NSMutableArray alloc] initWithCapacity:0];
217-
NSInteger _xCount = [_matrix count];
218-
NSInteger _yCount = 0;
219-
//如果第 1 個值為陣列
220-
if( [[_matrix objectAtIndex:0] isKindOfClass:[NSArray class]] )
112+
++_iteration;
113+
for( NSArray *_inputs in _patterns )
221114
{
222-
//即為 N 維陣列
223-
_xCount = [[_matrix objectAtIndex:0] count];
224-
_yCount = [_matrix count];
115+
[self _turningWeightsByInputs:_inputs];
225116
}
226117

227-
// 1 維陣列
228-
if( _yCount == 0 )
118+
if( _iteration >= _maxIteration )
229119
{
230-
for( int x=0; x<_xCount; x++ )
120+
if( nil != _trainingCompletion )
231121
{
232-
[_transposedMatrix addObject:[NSArray arrayWithObject:[_matrix objectAtIndex:x]]];
122+
_trainingCompletion(YES, _weights, _iteration);
233123
}
234124
}
235125
else
236126
{
237-
for( int x=0; x<_xCount; x++ )
127+
if( nil != _trainingIteraion )
238128
{
239-
//轉置,所以 x 總長度為 _yCount
240-
NSMutableArray *_newRows = [NSMutableArray arrayWithCapacity:_yCount];
241-
for( int y=0; y<_yCount; y++ )
242-
{
243-
//NSLog(@"x = %i, y = %i", x, y);
244-
if( [[_matrix objectAtIndex:y] isKindOfClass:[NSArray class]] )
245-
{
246-
[_newRows addObject:[[_matrix objectAtIndex:y] objectAtIndex:x]];
247-
}
248-
else
249-
{
250-
[_newRows addObject:[_matrix objectAtIndex:y]];
251-
}
252-
}
253-
[_transposedMatrix addObject:_newRows];
129+
_trainingIteraion(_iteration, _weights);
254130
}
131+
[self training];
255132
}
256-
return _transposedMatrix;
257133
}
258134

259-
#pragma --mark Public Hebbian Algorithm
260-
/*
261-
* @ 先轉置原始權重矩陣
262-
*/
263-
-(void)transposeWeights
135+
-(void)trainingWithCompletion:(KRHebbianCompletion)_completion
264136
{
265-
self._transposedWeights = [self transposeMatrix:self.weights];
137+
_trainingCompletion = _completion;
138+
[self training];
266139
}
267140

268-
/*
269-
* @ 再執行 Hebbian
270-
* - 求出 f(net) 並轉換成 sgn
271-
*/
272-
-(NSMutableArray *)training
141+
#pragma --mark Block Setters
142+
-(void)setTrainingCompletion:(KRHebbianCompletion)_block
143+
{
144+
_trainingCompletion = _block;
145+
}
146+
147+
-(void)setTrainingIteraion:(KRHebbianIteration)_block
273148
{
274-
[self transposeWeights];
275-
self.deltaWeights = [self _findNextDeltaWeightsWithFOfNet:[self _findFOfNet]];
276-
return _deltaWeights;
149+
_trainingIteraion = _block;
277150
}
278151

279152
@end

0 commit comments

Comments
 (0)