Module pywander.neural_network.basic

本脚本不具有使用价值

出于历史原因保留,可以作为初学者手写神经网络入门的参考。

除非有极高深的数学造诣,否则这样慢慢从简单到复杂,逐步摸索实践的过程是不能跳过去的。

Classes

class LinearModel (input_nodes=1, output_nodes=1, hidden_nodes=1, learning_rate=0.3)
Expand source code
class LinearModel(NeuralNetwork):
    """
    单隐藏层前馈神经网络
    无激活函数或者激活函数为 lambda x:x ,本质上仍然为线性模型,模拟能力有限,但深入其细节对于入门学习了解神经网络还是有所帮助的。

    """

    def __init__(self, input_nodes=1, output_nodes=1, hidden_nodes=1, learning_rate=0.3):
        super().__init__(input_nodes=input_nodes, output_nodes=output_nodes, learning_rate=learning_rate)
        # 隐藏层节点数
        self.h_nodes = hidden_nodes

        # 权重矩阵随机生成
        self.weight_matrix_hidden_output = None
        self.weight_matrix_input_hidden = None
        self.init_weight_matrix2()

    def init_weight_matrix(self):
        """
        经过一些实践就会发现初始权重矩阵有一些小技巧和注意事项,然后总的来说不太重要,因此不需要精确
        """
        self.weight_matrix_input_hidden = np.random.rand(self.h_nodes, self.i_nodes) - 0.5
        self.weight_matrix_hidden_output = np.random.rand(self.o_nodes, self.h_nodes) - 0.5

    def pre_process_input2(self, input_array):
        # 输入信号归一化
        norm = np.linalg.norm(input_array)
        input_array = input_array / norm
        return input_array

    def init_weight_matrix2(self):
        """
        以0为中心的正态分布采样
        """
        self.weight_matrix_input_hidden = np.random.normal(
            0.0, pow(self.h_nodes, -0.5), (self.h_nodes, self.i_nodes))
        self.weight_matrix_hidden_output = np.random.normal(
            0.0, pow(self.o_nodes, -0.5), (self.o_nodes, self.h_nodes))

    def query(self, input_array):
        input_array = self.pre_process_input2(input_array)

        hidden_input = np.dot(self.weight_matrix_input_hidden, input_array)
        # hidden_output = self.activation_function(hidden_input)
        hidden_output = hidden_input
        final_inputs = np.dot(self.weight_matrix_hidden_output, hidden_output)
        # final_outputs = self.activation_function(final_inputs)
        final_outputs = final_inputs
        return final_outputs

    def query_label(self, intput_array):
        final_outputs = self.query(intput_array)
        index = np.argmax(final_outputs)
        return self.label_list[index]

    def train(self, input_array, label):
        input_array = self.pre_process_input2(input_array)

        hidden_input = np.dot(self.weight_matrix_input_hidden, input_array)
        # hidden_output = self.activation_function(hidden_input)
        hidden_output = hidden_input
        final_inputs = np.dot(self.weight_matrix_hidden_output, hidden_output)
        # final_outputs = self.activation_function(final_inputs)
        final_outputs = final_inputs

        target_label_out = self.get_label_out(label)
        error_output = target_label_out - final_outputs

        error_hidden = np.dot(self.weight_matrix_hidden_output.transpose(), error_output)

        self.weight_matrix_hidden_output += self.lr * np.dot(to_column_vector(error_output),
                                                             to_row_vector(hidden_output))

        self.weight_matrix_input_hidden += self.lr * np.dot(to_column_vector(error_hidden), to_row_vector(input_array))

    def init_weight_matrix_old(self, init_array):
        """
        初始权重
        """
        column_vector_output = np.array([[1]])
        row_vector_hidden = np.random.rand(self.h_nodes)
        row_vector_hidden = to_row_vector(row_vector_hidden)
        # 隐藏层输出信号归一化 使得modifiers=1
        norm = np.linalg.norm(row_vector_hidden)
        row_vector_hidden = row_vector_hidden / norm
        column_vector_hidden = row_vector_to_column_vector(row_vector_hidden)

        # res = np.dot(row_vector_hidden, row_vector_hidden.transpose())
        # modifiers = res[0][0]

        self.weight_matrix_hidden_output = np.dot(column_vector_output, row_vector_hidden)
        # self.weight_matrix_hidden_output = self.weight_matrix_hidden_output / modifiers

        # 输入信号归一化 使得modifiers=1
        row_vector_input = to_row_vector(np.asarray(init_array, dtype=float))
        norm = np.linalg.norm(row_vector_input)
        row_vector_input = row_vector_input / norm
        # res = np.dot(row_vector_input, row_vector_input.transpose())
        # modifiers = res[0][0]

        self.weight_matrix_input_hidden = np.dot(column_vector_hidden, row_vector_input)
        # self.weight_matrix_input_hidden = self.weight_matrix_input_hidden / modifiers

单隐藏层前馈神经网络 无激活函数或者激活函数为 lambda x:x ,本质上仍然为线性模型,模拟能力有限,但深入其细节对于入门学习了解神经网络还是有所帮助的。

Ancestors

Methods

def init_weight_matrix(self)
Expand source code
def init_weight_matrix(self):
    """
    经过一些实践就会发现初始权重矩阵有一些小技巧和注意事项,然后总的来说不太重要,因此不需要精确
    """
    self.weight_matrix_input_hidden = np.random.rand(self.h_nodes, self.i_nodes) - 0.5
    self.weight_matrix_hidden_output = np.random.rand(self.o_nodes, self.h_nodes) - 0.5

经过一些实践就会发现初始权重矩阵有一些小技巧和注意事项,然后总的来说不太重要,因此不需要精确

def init_weight_matrix2(self)
Expand source code
def init_weight_matrix2(self):
    """
    以0为中心的正态分布采样
    """
    self.weight_matrix_input_hidden = np.random.normal(
        0.0, pow(self.h_nodes, -0.5), (self.h_nodes, self.i_nodes))
    self.weight_matrix_hidden_output = np.random.normal(
        0.0, pow(self.o_nodes, -0.5), (self.o_nodes, self.h_nodes))

以0为中心的正态分布采样

def init_weight_matrix_old(self, init_array)
Expand source code
def init_weight_matrix_old(self, init_array):
    """
    初始权重
    """
    column_vector_output = np.array([[1]])
    row_vector_hidden = np.random.rand(self.h_nodes)
    row_vector_hidden = to_row_vector(row_vector_hidden)
    # 隐藏层输出信号归一化 使得modifiers=1
    norm = np.linalg.norm(row_vector_hidden)
    row_vector_hidden = row_vector_hidden / norm
    column_vector_hidden = row_vector_to_column_vector(row_vector_hidden)

    # res = np.dot(row_vector_hidden, row_vector_hidden.transpose())
    # modifiers = res[0][0]

    self.weight_matrix_hidden_output = np.dot(column_vector_output, row_vector_hidden)
    # self.weight_matrix_hidden_output = self.weight_matrix_hidden_output / modifiers

    # 输入信号归一化 使得modifiers=1
    row_vector_input = to_row_vector(np.asarray(init_array, dtype=float))
    norm = np.linalg.norm(row_vector_input)
    row_vector_input = row_vector_input / norm
    # res = np.dot(row_vector_input, row_vector_input.transpose())
    # modifiers = res[0][0]

    self.weight_matrix_input_hidden = np.dot(column_vector_hidden, row_vector_input)
    # self.weight_matrix_input_hidden = self.weight_matrix_input_hidden / modifiers

初始权重

def pre_process_input2(self, input_array)
Expand source code
def pre_process_input2(self, input_array):
    # 输入信号归一化
    norm = np.linalg.norm(input_array)
    input_array = input_array / norm
    return input_array
def query(self, input_array)
Expand source code
def query(self, input_array):
    input_array = self.pre_process_input2(input_array)

    hidden_input = np.dot(self.weight_matrix_input_hidden, input_array)
    # hidden_output = self.activation_function(hidden_input)
    hidden_output = hidden_input
    final_inputs = np.dot(self.weight_matrix_hidden_output, hidden_output)
    # final_outputs = self.activation_function(final_inputs)
    final_outputs = final_inputs
    return final_outputs
def query_label(self, intput_array)
Expand source code
def query_label(self, intput_array):
    final_outputs = self.query(intput_array)
    index = np.argmax(final_outputs)
    return self.label_list[index]
def train(self, input_array, label)
Expand source code
def train(self, input_array, label):
    input_array = self.pre_process_input2(input_array)

    hidden_input = np.dot(self.weight_matrix_input_hidden, input_array)
    # hidden_output = self.activation_function(hidden_input)
    hidden_output = hidden_input
    final_inputs = np.dot(self.weight_matrix_hidden_output, hidden_output)
    # final_outputs = self.activation_function(final_inputs)
    final_outputs = final_inputs

    target_label_out = self.get_label_out(label)
    error_output = target_label_out - final_outputs

    error_hidden = np.dot(self.weight_matrix_hidden_output.transpose(), error_output)

    self.weight_matrix_hidden_output += self.lr * np.dot(to_column_vector(error_output),
                                                         to_row_vector(hidden_output))

    self.weight_matrix_input_hidden += self.lr * np.dot(to_column_vector(error_hidden), to_row_vector(input_array))
class NeuralNetwork (input_nodes=1, output_nodes=1, learning_rate=0.3, feature_range=(0.01, 0.99))
Expand source code
class NeuralNetwork:
    def __init__(self, input_nodes=1, output_nodes=1, learning_rate=0.3, feature_range=(0.01, 0.99)):
        # 权重、信号的值的约束范围
        self.feature_range = feature_range
        # 输入层节点数
        self.i_nodes = input_nodes
        # 输出层节点数
        self.o_nodes = output_nodes
        # label 任何神经网络都有其判断标识 只是有些和外界发生了对齐行为
        # 只有发生对齐行为的神经网络才会有训练行为
        self.label_list = ['' for _ in range(self.o_nodes)]
        self.label_out = []
        self.init_label_out()

        # 学习率
        self.lr = learning_rate

    def init_label_out(self):
        self.label_out = np.eye(self.o_nodes)

    def set_label_list(self, label_list):
        assert len(label_list) == self.o_nodes
        self.label_list = label_list

    def get_label_out(self, label):
        index = self.label_list.index(label)
        return self.label_out[index]

    def train(self, *args, **kwargs):
        pass

    def query(self, input_array):
        pass

    def preprocessing_minmax_scale(self, input_array):
        input_array = minmax_scale(input_array, feature_range=self.feature_range)
        return input_array

Subclasses

Methods

def get_label_out(self, label)
Expand source code
def get_label_out(self, label):
    index = self.label_list.index(label)
    return self.label_out[index]
def init_label_out(self)
Expand source code
def init_label_out(self):
    self.label_out = np.eye(self.o_nodes)
def preprocessing_minmax_scale(self, input_array)
Expand source code
def preprocessing_minmax_scale(self, input_array):
    input_array = minmax_scale(input_array, feature_range=self.feature_range)
    return input_array
def query(self, input_array)
Expand source code
def query(self, input_array):
    pass
def set_label_list(self, label_list)
Expand source code
def set_label_list(self, label_list):
    assert len(label_list) == self.o_nodes
    self.label_list = label_list
def train(self, *args, **kwargs)
Expand source code
def train(self, *args, **kwargs):
    pass
class SimpleFNN (input_nodes=1,
output_nodes=1,
hidden_nodes=1,
learning_rate=0.3,
feature_range=(0.01, 0.99))
Expand source code
class SimpleFNN(NeuralNetwork):
    """
    单隐藏层前馈神经网络
    有激活函数
    """

    def __init__(self, input_nodes=1, output_nodes=1, hidden_nodes=1, learning_rate=0.3, feature_range=(0.01, 0.99)):
        super().__init__(input_nodes=input_nodes, output_nodes=output_nodes, learning_rate=learning_rate,
                         feature_range=feature_range)
        # 隐藏层节点数
        self.h_nodes = hidden_nodes

        # 权重矩阵随机生成
        self.weight_matrix_hidden_output = None
        self.weight_matrix_input_hidden = None
        self.init_weight_matrix2()

        # 激活函数
        self.activation_function = lambda x: expit(x)
        self.inverse_activation_function = lambda x: logit(x)

    def init_label_out(self):
        label_out = np.eye(self.o_nodes)
        label_out = minmax_scale(label_out, feature_range=self.feature_range)
        self.label_out = label_out

    def init_weight_matrix(self):
        """
        经过一些实践就会发现初始权重矩阵有一些小技巧和注意事项,然后总的来说不太重要,因此不需要精确
        """
        self.weight_matrix_input_hidden = np.random.rand(self.h_nodes, self.i_nodes) - 0.5
        self.weight_matrix_hidden_output = np.random.rand(self.o_nodes, self.h_nodes) - 0.5

    def init_weight_matrix2(self):
        """
        以0为中心的正态分布采样
        """
        self.weight_matrix_input_hidden = np.random.normal(
            0.0, pow(self.h_nodes, -0.5), (self.h_nodes, self.i_nodes))
        self.weight_matrix_hidden_output = np.random.normal(
            0.0, pow(self.o_nodes, -0.5), (self.o_nodes, self.h_nodes))

    def query(self, input_array):
        input_array = self.preprocessing_minmax_scale(input_array)

        hidden_input = np.dot(self.weight_matrix_input_hidden, input_array)
        hidden_output = self.activation_function(hidden_input)

        final_inputs = np.dot(self.weight_matrix_hidden_output, hidden_output)
        final_outputs = self.activation_function(final_inputs)

        return final_outputs

    def back_query_label(self, label: str):
        index = self.label_list.index(label)
        final_outputs = to_column_vector(self.label_out[index])

        final_inputs = self.inverse_activation_function(final_outputs)

        hidden_outputs = np.dot(self.weight_matrix_hidden_output.transpose(), final_inputs)

        hidden_outputs = self.preprocessing_minmax_scale(hidden_outputs)

        hidden_inputs = self.inverse_activation_function(hidden_outputs)

        inputs = np.dot(self.weight_matrix_input_hidden.transpose(), hidden_inputs)
        inputs = self.preprocessing_minmax_scale(inputs)

        inputs = inputs.reshape(-1)
        return inputs

    def query_label(self, input_array):
        final_outputs = self.query(input_array)
        index = np.argmax(final_outputs)
        return self.label_list[index]

    def train(self, input_array, label: str):
        input_array = self.preprocessing_minmax_scale(input_array)

        hidden_input = np.dot(self.weight_matrix_input_hidden, input_array)
        hidden_output = self.activation_function(hidden_input)

        final_inputs = np.dot(self.weight_matrix_hidden_output, hidden_output)
        final_outputs = self.activation_function(final_inputs)

        target_label_out = self.get_label_out(label)
        error_output = target_label_out - final_outputs

        error_hidden = np.dot(self.weight_matrix_hidden_output.transpose(), error_output)

        self.weight_matrix_hidden_output += self.lr * np.dot(
            to_column_vector(error_output * final_outputs * (1 - final_outputs)),
            to_row_vector(hidden_output))

        self.weight_matrix_input_hidden += self.lr * np.dot(
            to_column_vector(error_hidden * hidden_output * (1 - hidden_output)), to_row_vector(input_array))

单隐藏层前馈神经网络 有激活函数

Ancestors

Methods

def back_query_label(self, label: str)
Expand source code
def back_query_label(self, label: str):
    index = self.label_list.index(label)
    final_outputs = to_column_vector(self.label_out[index])

    final_inputs = self.inverse_activation_function(final_outputs)

    hidden_outputs = np.dot(self.weight_matrix_hidden_output.transpose(), final_inputs)

    hidden_outputs = self.preprocessing_minmax_scale(hidden_outputs)

    hidden_inputs = self.inverse_activation_function(hidden_outputs)

    inputs = np.dot(self.weight_matrix_input_hidden.transpose(), hidden_inputs)
    inputs = self.preprocessing_minmax_scale(inputs)

    inputs = inputs.reshape(-1)
    return inputs
def init_label_out(self)
Expand source code
def init_label_out(self):
    label_out = np.eye(self.o_nodes)
    label_out = minmax_scale(label_out, feature_range=self.feature_range)
    self.label_out = label_out
def init_weight_matrix(self)
Expand source code
def init_weight_matrix(self):
    """
    经过一些实践就会发现初始权重矩阵有一些小技巧和注意事项,然后总的来说不太重要,因此不需要精确
    """
    self.weight_matrix_input_hidden = np.random.rand(self.h_nodes, self.i_nodes) - 0.5
    self.weight_matrix_hidden_output = np.random.rand(self.o_nodes, self.h_nodes) - 0.5

经过一些实践就会发现初始权重矩阵有一些小技巧和注意事项,然后总的来说不太重要,因此不需要精确

def init_weight_matrix2(self)
Expand source code
def init_weight_matrix2(self):
    """
    以0为中心的正态分布采样
    """
    self.weight_matrix_input_hidden = np.random.normal(
        0.0, pow(self.h_nodes, -0.5), (self.h_nodes, self.i_nodes))
    self.weight_matrix_hidden_output = np.random.normal(
        0.0, pow(self.o_nodes, -0.5), (self.o_nodes, self.h_nodes))

以0为中心的正态分布采样

def query(self, input_array)
Expand source code
def query(self, input_array):
    input_array = self.preprocessing_minmax_scale(input_array)

    hidden_input = np.dot(self.weight_matrix_input_hidden, input_array)
    hidden_output = self.activation_function(hidden_input)

    final_inputs = np.dot(self.weight_matrix_hidden_output, hidden_output)
    final_outputs = self.activation_function(final_inputs)

    return final_outputs
def query_label(self, input_array)
Expand source code
def query_label(self, input_array):
    final_outputs = self.query(input_array)
    index = np.argmax(final_outputs)
    return self.label_list[index]
def train(self, input_array, label: str)
Expand source code
def train(self, input_array, label: str):
    input_array = self.preprocessing_minmax_scale(input_array)

    hidden_input = np.dot(self.weight_matrix_input_hidden, input_array)
    hidden_output = self.activation_function(hidden_input)

    final_inputs = np.dot(self.weight_matrix_hidden_output, hidden_output)
    final_outputs = self.activation_function(final_inputs)

    target_label_out = self.get_label_out(label)
    error_output = target_label_out - final_outputs

    error_hidden = np.dot(self.weight_matrix_hidden_output.transpose(), error_output)

    self.weight_matrix_hidden_output += self.lr * np.dot(
        to_column_vector(error_output * final_outputs * (1 - final_outputs)),
        to_row_vector(hidden_output))

    self.weight_matrix_input_hidden += self.lr * np.dot(
        to_column_vector(error_hidden * hidden_output * (1 - hidden_output)), to_row_vector(input_array))