iOS人工智能交流模型4-用CC_ANN實現DNN網絡

大綱

  1. 神經網絡學習
  2. 常用模型分析
  3. iOS中的CoreML等閉源庫
  4. 通過bench_ios中的CC_ANN使用激活函數ReLU和Sigmoid實現DNN網絡。
  5. caffe、tensorflow等對比

目錄:

  1. 介紹一個CC_ANN使用例子
  2. 回顧神經網絡的構成
  3. 進行一次完整計算

CC_ANN是用oc封裝的一層和多層神經網絡例子,支持激活函數Sigmoid和ReLU

調用例子

//一次乘法的學習
//創建一個ANN網絡
CC_ANN *ann=[[CC_ANN alloc]init];

//學習100次
int count=100
[ann autoTrainTwoToOne:@[@[@[@(0.2),@(0.6)],@(0.12)],@[@[@(0.4),@(0.6)],@(0.24)],@[@[@(0.3),@(0.4)],@(0.12)]] activeFunction:ActiveFunctionTypeSigmoid trainTimes:count];
double predict1=[ann calWithInput:@[@(0.2),@(0.6)]];
double predict2=[ann calWithInput:@[@(0.4),@(0.6)]];
double predict3=[ann calWithInput:@[@(0.3),@(0.4)]];
double predict4=[ann calWithInput:@[@(0.4),@(0.5)]];
NSLog(@"p1=%f p2=%f p3=%f p4=%f",predict1,predict2,predict3,predict4);

//打印結果
p1=0.121306 p2=0.237448 p3=0.122096 p4=0.208426
耗時0.002秒

//學習1000次
int count=1000
//打印結果
p1=0.120000 p2=0.239999 p3=0.120001 p4=0.209638
耗時0.026秒

//學習10000次
int count=10000
//打印結果
p1=0.120000 p2=0.240000 p3=0.120000 p4=0.209638
耗時0.28秒

例子結論:

  1. 學習次數越多,對例子的還原越正確。如2*6越來越接近12
  2. 學習次數到達一定次數後,對預測的精確度不會再提高。如我們沒有教過4*5,但是預測答案接近20,在學習1000次後,達到20.9638,但是學習10000次也沒有將精度再次提高

這個例子符合神經網絡的特徵

下面看下如何構建一層神經網絡,具體的計算方法。
img1

線性函數和sigmoid函數
LinearRegression模型:img2
sigmoid函數:img3

隱層決定了最終的分類效果
img4

可以看到,隱層越多,分類效果越好,因爲可以轉折的點更多。實際上,Kolmogorov理論指出:雙隱層感知器就足以解決任何複雜的分類問題。
但是,過多的隱層和神經元結點會帶來過擬合問題,不要試圖降低神經網絡參數量來減緩過擬合,用正則化或者dropout。

神經網絡結構
img5

傳遞函數/激活函數
每一層傳遞使用wx+b,對每一個輸出使用sigmoid、tanh、relu等激活函數使線性的結果非線性化。
爲什麼需要傳遞函數?
簡單理解上,如果不加激活函數,無論多少層隱層,最終的結果還是原始輸入的線性變化,這樣一層隱層就可以達到結果,就沒有多層感知器的意義了。所以每個隱層都會配一個激活函數,提供非線性變化。

BP算法
一個反饋網絡,類似生物的反饋網絡,和人走路不會摔倒一樣,每一次輸出都會有反饋去修正誤差,使下一次結果更接近理想結果。
img6

以三層感知器爲例做計算:
網絡結構
img7

可以用到的公式爲:
img8
img9

代入參數:
img10

兩個輸入;
隱層: b1, w1, w2, w3, w4 (都有初始值) 計算一個合理的初始值可以使用前面提到的HE初始化、隨機初始化和pre-train初始化
輸出層:b2, w5, w6, w7, w8(賦了初始值)
這裏使用sigmoid激活函數
img11

用E來衡量誤差大小,爲反饋提供支持:
img12

獲得E後反向計算誤差:
對E求導就可計算出誤差梯度
img13

計算出w5、w6、w7、w8的誤差梯度:
誤差梯度乘以學習率即是需要調整的誤差值
img14

同理,再向上一級推導出w1-w4的誤差值:
img15

完成一次反向傳播:
求誤差對w5的偏導過程 參數更新: 求誤差對w1的偏導 注意,w1對兩個輸出的誤差都有影響
通過以上過程可以更新所有權重,就可以再次迭代更新了,直到滿足條件。

可以提供的數學函數:

@interface CC_Math : NSObject

+ (double)sign:(double)input;

/**
 *  激活函數
 */
+ (double)sigmoid:(double)input;
+ (double)reLU:(double)input;

/**
 *  雙s曲線
 */
+ (double)doubleS:(int)input;

/**
 *  標準正態分佈
 */
+ (double)randn:(double)input;

/**
 *  獲得初始化權重
 *  length w個數
 */
+ (NSMutableArray *)getW_positive_unitball:(int)length;
/**
 *  weight = np.random.randn(in_node, out_node)/np.sqrt(in_node)
 */
+ (NSMutableArray *)getW_XavierFiller:(int)length;
/**
 *  Xavier論文中使用的激活函數是tanh函數,而神經網絡中使用較廣泛的是relu激活函數,所以提出此方法。
    weight = np.random.randn(in_node, out_node)/np.sqrt(in_node/2)
 */
+ (NSMutableArray *)getW_MSRAFiller:(int)length;

@end

可以提供的ANN函數

typedef enum : NSUInteger {
    ActiveFunctionTypeReLU,
    ActiveFunctionTypeSigmoid,//如使用sigmoid 輸入輸出範圍在[-1,1]
} ActiveFunctionType;

@interface CC_ANN : NSObject

/**
 *  訓練結束後可計算結果
 */
- (double)calWithInput:(NSArray *)input;

//- (double)calWithInput_twolevel:(NSArray *)input;

/**
 *  一層深度學習
 *  samples 學習樣本 多個樣本以數組形式
    例:@[@[@[@(0.2),@(0.6)],@(0.12)],@[@[@(0.4),@(0.6)],@(0.24)]]
 *  weights 初始化權重 一層深度 2個輸入1個輸出需要權重 2^2+2=6個初始值
 *  learningRate 學習率 選一個較小值 如0.4
 *  activeFunction 激活函數
 *  times 訓練次數
 */
- (void)trainTwoToOne:(NSArray *)samples weights:(NSArray *)weights learningRate:(double)learningRate activeFunction:(ActiveFunctionType)activeFunction trainTimes:(int)times;

/**
 *  一層深度學習 自動尋找最佳學習率 自動獲取初始化權值w
 *  activeFunction 激活函數
 *  times 訓練次數
 */
- (void)autoTrainTwoToOne:(NSArray *)samples activeFunction:(ActiveFunctionType)activeFunction trainTimes:(int)times;

/**
 *  一層深度學習 自動尋找最佳學習率 自動獲取初始化權值w
 *  errorRate 到最小錯誤率前不會停止學習
 */
- (void)autoTrainTwoToOne:(NSArray *)samples activeFunction:(ActiveFunctionType)activeFunction untilErrorRate:(double)errorRate;

- (void)trainTwoToOne:(NSArray *)samples trainTimes:(int)times deep:(int)deep;
- (void)trainTwoToOne:(NSArray *)samples trainTimes:(int)times;

@end

demo下載
https://github.com/gwh111/bench_ios

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章