《统计学习方法》学习之一:感知机

一、感知机模型
  在一个n维空间中,存在一个超平面,可以将特征向量分为+1和-1两个类别。(具体内容可以参考李航《统计学习方法》一书)。

二、代码实现

import numpy as np


def perceptron_algorithm_01(x_input, y_input, lr=1.0, weight_init='zeros', bias_init='zeros', max_iteration=1000):
    '''
    :param x_input:输入的特征向量,x∈R^n。
    :param y_input: ,欸一个特征向量对应的类别,y∈{-1, +1}。
    :param lr: 学习率,默认为1.0。
    :param weight_init: 权重初始化方法,是['zeros', 'ones', 'random']三个中的一个。
    :param bias_init: 偏置初始化方法,是['zeros', 'ones', 'random']三个中的一个。
    :param max_iteration: 最大迭代次数,默认为1000。
    :return: 权重weight和偏置bias
    '''
    assert len(x_input) == len(y_input)

    if weight_init not in ['zeros', 'ones', 'random']:
        raise ValueError("""Please choose weight_init parameter correctly!\n
                            weight_init: one of these choices:'zeros', 'ones', 'random'""")

    if bias_init not in ['zeros', 'ones', 'random']:
        raise ValueError("""Please choose bias_init parameter correctly!\n
                            bias_init: one of these choices:'zeros', 'ones', 'random'""")

    x_input = np.array(x_input)
    y_input = np.array(y_input)

    if weight_init == 'zeros':
        weight = np.zeros(shape=[x_input.shape[1]])
    elif weight_init == 'ones':
        weight = np.ones(shape=[x_input.shape[1]])
    elif weight_init == 'random':
        weight = np.random.random(size=(x_input.shape[1]))

    if bias_init == 'zeros':
        bias = 0
    elif bias_init == 'ones':
        bias = 1
    elif bias_init == 'random':
        bias = np.random.random()

    iteration = 0
    while True:
        x, y = None, None
        for i, j in zip(x_input, y_input):
            if j * (sum(weight * i) + bias) <= 0:
                x = i
                y = j
                break
        if x is not None and y is not None and iteration < max_iteration:
            weight += lr * y * x
            bias += lr * y
            iteration += 1
        else:
            break

    return weight, bias


def perceptron_algorithm_02(x_input, y_input, lr=1.0, alpha_init='zeros', bias_init='zeros', max_iteration=1000):
    '''
    :param x_input:输入的特征向量,x∈R^n。
    :param y_input: ,欸一个特征向量对应的类别,y∈{-1, +1}。
    :param lr: 学习率,默认为1.0。
    :param alpha_init: 权重初始化方法,是['zeros', 'ones', 'random']三个中的一个。
    :param bias_init: 偏置初始化方法,是['zeros', 'ones', 'random']三个中的一个。
    :param max_iteration: 最大迭代次数,默认为1000。
    :return: 权重weight和偏置bias
    '''
    assert len(x_input) == len(y_input)
    x_input = np.array(x_input)
    y_input = np.array(y_input)

    if alpha_init not in ['zeros', 'ones', 'random']:
        raise ValueError("""Please choose alpha_init parameter correctly!\n
                            alpha_init: one of these choices:'zeros', 'ones', 'random'""")

    if bias_init not in ['zeros', 'ones', 'random']:
        raise ValueError("""Please choose bias_init parameter correctly!\n
                            bias_init: one of these choices:'zeros', 'ones', 'random'""")

    if alpha_init == 'zeros':
        alpha = np.zeros(shape=[x_input.shape[0]])
    elif alpha_init == 'ones':
        alpha = np.ones(shape=[x_input.shape[0]])
    elif alpha_init == 'random':
        alpha = np.random.random(size=(x_input.shape[0]))

    if bias_init == 'zeros':
        bias = 0
    elif bias_init == 'ones':
        bias = 1
    elif bias_init == 'random':
        bias = np.random.random()

    gram_matrix = np.zeros(shape=[x_input.shape[0], x_input.shape[0]])
    for i in range(x_input.shape[0]):
        for j in range(i, x_input.shape[0]):
            gram_matrix[i][j] = gram_matrix[j][i] = sum(x_input[i]*x_input[j])

    iteration = 0
    while True:
        pos = -1
        for i in range(len(x_input)):
            if y_input[i] * (sum(alpha[j] * y_input[j] * gram_matrix[i][j] for j in range(len(x_input))) + bias) <= 0:
                pos = i
                break

        if pos != -1 and iteration < max_iteration:
            alpha[pos] += lr
            bias += lr * y_input[pos]
            iteration += 1
        else:
            break

    weight = np.sum((alpha[i] * y_input[i] * x_input[i] for i in range(len(x_input))), axis=0)

    return weight, bias


if __name__ == '__main__':
    x = [[3, 3], [4, 3], [1, 1]]
    y = [1, 1, -1]
    w, b = perceptron_algorithm_01(x, y, lr=1.0, weight_init='zeros', bias_init='zeros')
    print('感知机学习算法的原始形式:')
    print('所得权重:', w)
    print('所得偏置:', b)

    w, b = perceptron_algorithm_02(x, y, lr=1.0, alpha_init='zeros', bias_init='zeros')
    print('感知机学习算法的对偶形式:')
    print('所得权重:', w)
    print('所得偏置:', b)

  结果如下:

感知机学习算法的原始形式:
所得权重: [1. 1.]
所得偏置: -3.0
感知机学习算法的对偶形式:
所得权重: [1. 1.]
所得偏置: -3.0

三、结论
  感知机是一种极为简单的机器学习模型,对初始值敏感,在实际中较少用到。

你可能感兴趣的:(机器学习,统计学习方法,感知机)