- 徑向基函數 RBF Function
- 徑向基網路 RBF Network Model
https://www.youtube.com/watch?v=1Cw45yNm6VA
徑向基函數
關於 y 軸對稱,且在 x=0 時達到最大值(峰值),峰值一般為 1
如高斯函數:
徑向基函數也可以是多維的,但不論輸入向量是多少維,輸出都是一個標量值(為輸入向量和中心向量的距離,一般為歐氏距離,記為 r)
輸入向量和中心向量維數相同,否則無法計算距離
高斯徑向基函數公式:
可以看出,和中心向量越近,函數值越接近 1
在應用中會進行適當的放縮
Ricker 小波函數(墨西哥帽子函數)
徑向基函數網路
即可用於分類,也可用於回歸問題
將多個徑向基函數加權求和,每個徑向基函數都接受一個帶權重的輸入,從而對輸出進行預測
X 為輸入向量,c 為中心向量,因此括號中的值為 r
p 是所選的徑向基函數
a 是每個函數的權重,一般為向量形式
b 是每個輸入對應的權重
看下下面的圖立刻就能明白原理了:
箭頭表示公式中的全部係數
輸入和徑向基函數的箭頭表示 b
徑向基函數和求和間的箭頭表示 a
bias 輸出恆為 1,因此不需要輸入,之後誠意對應的係數,相當於無論輸入什麼,都有一個對應係數直接加在輸出上。它很有用,尤其在輸入為 0 時,也能保證依然有值可以輸出。
多個求和函數,求出的和的最大值即為對應的預測類別
以鳶尾花資料集為例:
輸入為四維向量,輸出三種類別(採用 One-hot 編碼)
徑向基函數網路的長期記憶向量包含以下部分:
- 輸入係數
- 輸出係數(求和係數)
- 徑向基函數放縮範圍(在各維度範圍相同)
- 徑向基函數中心向量
構造 rbf 函數網路
typedef struct RBF_NETWORK {
RBF_FUNCTION rbf;
unsigned int ltm_size;
unsigned int input_count;
unsigned int rbf_count;
unsigned int output_count;
double *long_term_memory;
double *rbf_output;
double *weighted_input;
unsigned int *rbf_index;
unsigned int index_input_weights;
unsigned int index_output_weights;
} RBF_NETWORK;
RBF_NETWORK* RBFNetworkCreate(RBF_FUNCTION rbf, // 指定使用的函數,如高斯函數
int input_count, // 輸入通道數
int rbf_count, // rbf 函數數目
int output_count) // 輸出通道數
{
RBF_NETWORK *result;
int i;
/* calculate input and output weight counts
add 1 to output to account for an extra bias node */
const int inputWeightCount = input_count * rbf_count;
const int outputWeightCount = (rbf_count + 1) * output_count;
const int rbfParams = (input_count + 1) * rbf_count;
/* allocate structure */
result = (RBF_NETWORK*)calloc(1,sizeof(RBF_NETWORK));
result->input_count = input_count;
result->rbf_count = rbf_count;
result->rbf = rbf;
result->output_count = output_count;
result->rbf_index = (unsigned int*)calloc(rbf_count,sizeof(int));
result->rbf_output = (double*)calloc(rbf_count+1,sizeof(double));
result->weighted_input = (double*)calloc(input_count,sizeof(double));
result->ltm_size = inputWeightCount + outputWeightCount + rbfParams;
result->long_term_memory = (double*)calloc(result->ltm_size,sizeof(double));
result->index_input_weights = 0;
result->index_output_weights = inputWeightCount + rbfParams;
for (i = 0; i < rbf_count; i++) {
result->rbf_index[i] = inputWeightCount + ((input_count + 1) * i);
}
return result;
}
計算 rbf 網路輸出
void RBFNetworkComputeRegression(RBF_NETWORK *network, double *input, double *output) {
unsigned int inputIndex, outputIndex, rbfIndex, memoryIndex;
double sum;
/* first, compute the output values of each of the RBFs
Add in one additional RBF output for bias (always set to one). */
network->rbf_output[network->rbf_count] = 1; // bias
for (rbfIndex = 0; rbfIndex < network->rbf_count; rbfIndex++) {
/* weight the input */
for (inputIndex = 0; inputIndex < network->input_count; inputIndex++) {
memoryIndex = network->index_input_weights + (rbfIndex * network->input_count) + inputIndex;
network->weighted_input[inputIndex] = input[inputIndex] * network->long_term_memory[memoryIndex];
}
/* calculate the rbf */
network->rbf_output[rbfIndex] = network->rbf(network->weighted_input,0,network->input_count,network->long_term_memory,network->rbf_index[rbfIndex]);
}
/* second, calculate the output, which is the result of the weighted result of the RBF's. */
for (outputIndex = 0; outputIndex < network->output_count; outputIndex++) {
sum = 0;
for (rbfIndex = 0; rbfIndex <= network->rbf_count; rbfIndex++) {
/* add 1 to rbf length for bias */
memoryIndex = network->index_output_weights + (outputIndex * (network->rbf_count + 1)) + rbfIndex;
sum += network->rbf_output[rbfIndex] * network->long_term_memory[memoryIndex];
}
output[outputIndex] = sum;
}
}