神经网络代码实现(用手写数字识别数据集实验)

目录

一、前言

二、神经网络架构

三、算法实现

         1、导入包

         2、实现类

         3、训练函数

        4、权重参数矩阵初始化

        5、参数矩阵变换向量

         6、向量变换权重参数矩阵

         7、进行梯度下降

                7.1、损失函数

                        7.1.1、前向传播

                7.2、反向传播

        8、预测函数

四、完整代码

 五、手写数字识别


一、前言

        读者需要了解神经网络的基础知识,可以参考神经网络(深度学习,计算机视觉,得分函数,损失函数,前向传播,反向传播,激活函数)

        本文为大家详细的描述了,实现神经网络的逻辑,代码。并且用手写识别来实验,结果基本实现了神经网络的要求。

二、神经网络架构

        想一想:

        1.输入数据:特征值(手写数字识别是像素点,784个特征)

        2.W1,W2,W3矩阵的形状

        3.前向传播

        4.激活函数(用Sigmoid)

        5.反向传播

        6.偏置项

        7.损失(\hat{y}-y)

        8.得出W1,W2,W3对损失有多大影响,公式如下:

        \begin{matrix} \delta(4)=a(4)-y\\ \delta(3)=(\Theta ^3)^T\delta(4)*g'(z^{(3)})\\ \delta(2)=(\Theta ^2)^T\delta(3)*g'(z^{(2)})\\ \delta(1) =is \; for\;input\;layer,\;we\;can't\;change\;it\\ g'-sigmoid\;gradient\\ g'(z)=\frac{\partial }{\partial z}g(z)=g(z)(1-g(z));\;where\;g(z)=\frac{1}{1+e^{-z}} \end{matrix}

        算法流程(简便版):

        \begin{matrix} for\;i=1\;to\;m\\ \;set\;a(1)=x^{(i)}\\ perform\;forward\;propagation\;to\;compute\;a(1)\;for\;l=2,3...L\\ Using\;y^{(i)},compute\;\delta(L)=a^{(l)}-y^{(i)}\\ compute\;\delta(L-1)\;\delta(L-2)...\delta(2)\\ \Delta _{ij}^{(l)}:\Delta _{ij}^{(l)}+a_{j}^{(l)}\delta_i^{(l+1)}(or\;in\;vectorized\;form\;\Delta^{(l)}=\Delta^{(l)}+\delta^{(l+1)}(a(l))^T) \end{matrix}

         

三、算法实现

         1、导入包

import  numpy as np
from Neural_Network_Lab.utils.features import prepare_for_training
from Neural_Network_Lab.utils.hypothesis import sigmoid,sigmoid_gradient

           这里utils包用来封装数据预处理,和Sigmoid函数

          数据预处理:


import numpy as np
from .normalize import normalizedef generate_polynomials(dataset, polynomial_degree, normalize_data=False):"""变换方法:x1, x2, x1^2, x2^2, x1*x2, x1*x2^2, etc."""features_split = np.array_split(dataset, 2, axis=1)dataset_1 = features_split[0]dataset_2 = features_split[1](num_examples_1, num_features_1) = dataset_1.shape(num_examples_2, num_features_2) = dataset_2.shapeif num_examples_1 != num_examples_2:raise ValueError('Can not generate polynomials for two sets with different number of rows')if num_features_1 == 0 and num_features_2 == 0:raise ValueError('Can not generate polynomials for two sets with no columns')if num_features_1 == 0:dataset_1 = dataset_2elif num_features_2 == 0:dataset_2 = dataset_1num_features = num_features_1 if num_features_1 < num_examples_2 else num_features_2dataset_1 = dataset_1[:, :num_features]dataset_2 = dataset_2[:, :num_features]polynomials = np.empty((num_examples_1, 0))for i in range(1, polynomial_degree + 1):for j in range(i + 1):polynomial_feature = (dataset_1 ** (i - j)) * (dataset_2 ** j)polynomials = np.concatenate((polynomials, polynomial_feature), axis=1)if normalize_data:polynomials = normalize(polynomials)[0]return polynomials

        Sigmoid函数:

import numpy as npdef sigmoid(matrix):"""Applies sigmoid function to NumPy matrix"""return 1 / (1 + np.exp(-matrix))

         2、实现类

        多层感知机 初始化:数据,标签,网络层次(用列表表示如三层[784,25,10]表示输入层784个神经元,25个隐藏层神经元,10个输出层神经元),数据是否标准化处理。

class MultilayerPerceptron:def __init__(self,data,labels,layers,normalize_data=False):data_processed = prepare_for_training(data,normalize_data=normalize_data)[0]self.data = data_processedself.labels = labelsself.layers = layers #  [  784 ,25 ,10]self.normalize_data = normalize_dataself.thetas = MultilayerPerceptron.thetas_init(layers)

         3、训练函数

        输入迭代次数,学习率,进行梯度下降算法,更新权重参数矩阵,得到最终的权重参数矩阵,和损失值。矩阵不好进行更新操作,可以把它拉成向量。

    def train(self,max_ietrations = 1000,alpha = 0.1):#方便矩阵更新 拉长  把矩阵拉成向量unrolled_theta = MultilayerPerceptron.thetas_unroll(self.thetas)(optimized_theta, cost_history) = MultilayerPerceptron.gradient_descent(self.data,self.labels,unrolled_theta,self.layers,max_ietrations,alpha)self.thetas = MultilayerPerceptron.thetas_roll(optimized_theta,self.layers)return self.thetas,cost_history

        4、权重参数矩阵初始化

        根据网络层次可以确定,矩阵的大小,用字典存储。

    @staticmethoddef thetas_init(layers):num_layers = len(layers)thetas = {} #用字典形式 key:表示第几层 vlues:权重参数矩阵for layer_index in range(num_layers-1):'''会执行两次: 得到两组参数矩阵 25 * 785 , 10 * 26'''in_count = layers[layer_index]out_count = layers[layer_index+1]#初始化 初始值小#这里需要考虑偏置项,偏置的个数与输出的个数一样thetas[layer_index]=np.random.rand(out_count,in_count+1) * 0.05 #加一列输入特征return thetas

        5、参数矩阵变换向量

        将权重参数矩阵变换成向量

    @staticmethoddef thetas_unroll(thetas):#拼接成一个向量num_theta_layers = len(thetas)unrolled_theta = np.array([])for theta_layer_index in range(num_theta_layers):unrolled_theta = np.hstack((unrolled_theta,thetas[theta_layer_index].flatten()))return unrolled_theta

         6、向量变换权重参数矩阵

        后边前向传播时需要进行矩阵乘法,需要变换回来

    @staticmethoddef thetas_roll(unrolled_theta,layers):num_layers = len(layers)thetas = {}unrolled_shift = 0for layer_index in range(num_layers - 1):in_count = layers[layer_index]out_count = layers[layer_index + 1]thetas_width = in_count + 1thetas_height = out_countthetas_volume = thetas_width * thetas_heightstart_index = unrolled_shiftend_index =unrolled_shift + thetas_volumelayer_theta_unrolled = unrolled_theta[start_index:end_index]thetas[layer_index] = layer_theta_unrolled.reshape((thetas_height,thetas_width))unrolled_shift = unrolled_shift + thetas_volumereturn thetas

         7、进行梯度下降

                1. 损失函数,计算损失值

                2. 计算梯度值

                3. 更新参数

                那么得先要实现损失函数,计算损失值。

                7.1、损失函数

                        实现损失函数,得到损失值得要实现前向传播走一次

                        7.1.1、前向传播
    @staticmethoddef feedforword_propagation(data,thetas,layers):num_layers = len(layers)num_examples = data.shape[0]in_layer_activation = data #输入层#逐层计算 隐藏层for layer_index in range(num_layers - 1):theta = thetas[layer_index]out_layer_activation = sigmoid(np.dot(in_layer_activation,theta.T)) #输出层# 正常计算之后是num_examples * 25 ,但是要考虑偏置项 变成num_examples * 26out_layer_activation = np.hstack((np.ones((num_examples,1)),out_layer_activation))in_layer_activation = out_layer_activation#返回输出层结果,不要偏置项return in_layer_activation[:,1:]

                损失函数:

    @staticmethoddef cost_function(data,labels,thetas,layers):num_layers = len(layers)num_examples = data.shape[0]num_labels = layers[-1]#前向传播走一次predictions = MultilayerPerceptron.feedforword_propagation(data,thetas,layers)#制作标签,每一个样本的标签都是one-dotbitwise_labels = np.zeros((num_examples,num_labels))for example_index in range(num_examples):bitwise_labels[example_index][labels[example_index][0]] = 1#咱们的预测值是概率值y= 7 [0,0,0,0,0,0,1,0,0,0]    在正确值的位置上概率越大越好 在错误值的位置上概率越小越好bit_set_cost = np.sum(np.log(predictions[bitwise_labels == 1]))bit_not_set_cost = np.sum(np.log(1 - predictions[bitwise_labels == 0]))cost = (-1/num_examples) * (bit_set_cost+bit_not_set_cost)return cost

                7.2、反向传播

                在梯度下降的过程中,要实现参数矩阵的更新,必须要实现反向传播。利用上述的公式,进行运算即可得到。

    @staticmethoddef back_propagation(data,labels,thetas,layers):num_layers = len(layers)(num_examples,num_features) = data.shapenum_label_types = layers[-1]deltas = {} # 算出每一层对结果的影响#初始化for layer_index in  range(num_layers - 1):in_count = layers[layer_index]out_count = layers[layer_index + 1]deltas[layer_index] = np.zeros((out_count,in_count+1)) #25 * 785 10 *26for example_index in range(num_examples):layers_inputs = {}layers_activations = {}layers_activation = data[example_index,:].reshape((num_features,1))layers_activations[0] = layers_activation#逐层计算for layer_index in range(num_layers - 1):layer_theta = thetas[layer_index]  #得到当前的权重参数值 : 25 *785 10 *26layer_input = np.dot(layer_theta,layers_activation) # 第一次 得到 25 * 1 第二次: 10 * 1layers_activation = np.vstack((np.array([[1]]),sigmoid(layer_input))) #完成激活函数,加上一个偏置参数layers_inputs[layer_index+1] = layer_input # 后一层计算结果layers_activations[layer_index +1] = layers_activation # 后一层完成激活的结果output_layer_activation = layers_activation[1:,:]#计算输出层和结果的差异delta = {}#标签处理bitwise_label = np.zeros((num_label_types,1))bitwise_label[labels[example_index][0]] = 1#计算输出结果和真实值之间的差异delta[num_layers-1] = output_layer_activation - bitwise_label #输出层#遍历 L,L-1,L-2...2for layer_index in range(num_layers - 2,0,-1):layer_theta = thetas[layer_index]next_delta = delta[layer_index+1]layer_input = layers_inputs[layer_index]layer_input = np.vstack((np.array((1)),layer_input))#按照公式计算delta[layer_index] = np.dot(layer_theta.T,next_delta)*sigmoid(layer_input)#过滤掉偏置参数delta[layer_index] = delta[layer_index][1:,:]#计算梯度值for layer_index in  range(num_layers-1):layer_delta = np.dot(delta[layer_index+1],layers_activations[layer_index].T)  #微调矩阵deltas[layer_index] = deltas[layer_index] + layer_delta #第一次25 * 785 第二次 10 * 26for layer_index in range(num_layers-1):deltas[layer_index] = deltas[layer_index] * (1/num_examples) #公式return deltas

        实现一次梯度下降:

    @staticmethoddef gradient_step(data,labels,optimized_theta,layers):theta = MultilayerPerceptron.thetas_roll(optimized_theta,layers)#反向传播BPthetas_rolled_gradinets = MultilayerPerceptron.back_propagation(data,labels,theta,layers)thetas_unrolled_gradinets = MultilayerPerceptron.thetas_unroll(thetas_rolled_gradinets)return thetas_unrolled_gradinets

         实现梯度下降:

    @staticmethoddef gradient_descent(data,labels,unrolled_theta,layers,max_ietrations,alpha):#1. 计算损失值#2. 计算梯度值#3. 更新参数optimized_theta = unrolled_theta #最好的theta值cost_history = []  #损失值的记录for i in range(max_ietrations):if i % 10 == 0 :print("当前迭代次数:",i)cost  = MultilayerPerceptron.cost_function(data,labels,MultilayerPerceptron.thetas_roll(optimized_theta,layers),layers)cost_history.append(cost)theta_gradient = MultilayerPerceptron.gradient_step(data,labels,optimized_theta,layers)optimized_theta = optimized_theta - alpha * theta_gradientreturn optimized_theta,cost_history

        8、预测函数

        输入测试数据,前向传播走一次,得到预测值

    def predict(self,data):data_processed = prepare_for_training(data,normalize_data = self.normalize_data)[0]num_examples = data_processed.shape[0]predictions = MultilayerPerceptron.feedforword_propagation(data_processed,self.thetas,self.layers)return np.argmax(predictions,axis=1).reshape((num_examples,1))

四、完整代码

import  numpy as np
from Neural_Network_Lab.utils.features import prepare_for_training
from Neural_Network_Lab.utils.hypothesis import sigmoid,sigmoid_gradientclass MultilayerPerceptron:def __init__(self,data,labels,layers,normalize_data=False):data_processed = prepare_for_training(data,normalize_data=normalize_data)[0]self.data = data_processedself.labels = labelsself.layers = layers #  [  784 ,25 ,10]self.normalize_data = normalize_dataself.thetas = MultilayerPerceptron.thetas_init(layers)def predict(self,data):data_processed = prepare_for_training(data,normalize_data = self.normalize_data)[0]num_examples = data_processed.shape[0]predictions = MultilayerPerceptron.feedforword_propagation(data_processed,self.thetas,self.layers)return np.argmax(predictions,axis=1).reshape((num_examples,1))def train(self,max_ietrations = 1000,alpha = 0.1):#方便矩阵更新 拉长  把矩阵拉成向量unrolled_theta = MultilayerPerceptron.thetas_unroll(self.thetas)(optimized_theta, cost_history) = MultilayerPerceptron.gradient_descent(self.data,self.labels,unrolled_theta,self.layers,max_ietrations,alpha)self.thetas = MultilayerPerceptron.thetas_roll(optimized_theta,self.layers)return self.thetas,cost_history@staticmethoddef gradient_descent(data,labels,unrolled_theta,layers,max_ietrations,alpha):#1. 计算损失值#2. 计算梯度值#3. 更新参数optimized_theta = unrolled_theta #最好的theta值cost_history = []  #损失值的记录for i in range(max_ietrations):if i % 10 == 0 :print("当前迭代次数:",i)cost  = MultilayerPerceptron.cost_function(data,labels,MultilayerPerceptron.thetas_roll(optimized_theta,layers),layers)cost_history.append(cost)theta_gradient = MultilayerPerceptron.gradient_step(data,labels,optimized_theta,layers)optimized_theta = optimized_theta - alpha * theta_gradientreturn optimized_theta,cost_history@staticmethoddef gradient_step(data,labels,optimized_theta,layers):theta = MultilayerPerceptron.thetas_roll(optimized_theta,layers)#反向传播BPthetas_rolled_gradinets = MultilayerPerceptron.back_propagation(data,labels,theta,layers)thetas_unrolled_gradinets = MultilayerPerceptron.thetas_unroll(thetas_rolled_gradinets)return thetas_unrolled_gradinets@staticmethoddef back_propagation(data,labels,thetas,layers):num_layers = len(layers)(num_examples,num_features) = data.shapenum_label_types = layers[-1]deltas = {} # 算出每一层对结果的影响#初始化for layer_index in  range(num_layers - 1):in_count = layers[layer_index]out_count = layers[layer_index + 1]deltas[layer_index] = np.zeros((out_count,in_count+1)) #25 * 785 10 *26for example_index in range(num_examples):layers_inputs = {}layers_activations = {}layers_activation = data[example_index,:].reshape((num_features,1))layers_activations[0] = layers_activation#逐层计算for layer_index in range(num_layers - 1):layer_theta = thetas[layer_index]  #得到当前的权重参数值 : 25 *785 10 *26layer_input = np.dot(layer_theta,layers_activation) # 第一次 得到 25 * 1 第二次: 10 * 1layers_activation = np.vstack((np.array([[1]]),sigmoid(layer_input))) #完成激活函数,加上一个偏置参数layers_inputs[layer_index+1] = layer_input # 后一层计算结果layers_activations[layer_index +1] = layers_activation # 后一层完成激活的结果output_layer_activation = layers_activation[1:,:]#计算输出层和结果的差异delta = {}#标签处理bitwise_label = np.zeros((num_label_types,1))bitwise_label[labels[example_index][0]] = 1#计算输出结果和真实值之间的差异delta[num_layers-1] = output_layer_activation - bitwise_label #输出层#遍历 L,L-1,L-2...2for layer_index in range(num_layers - 2,0,-1):layer_theta = thetas[layer_index]next_delta = delta[layer_index+1]layer_input = layers_inputs[layer_index]layer_input = np.vstack((np.array((1)),layer_input))#按照公式计算delta[layer_index] = np.dot(layer_theta.T,next_delta)*sigmoid(layer_input)#过滤掉偏置参数delta[layer_index] = delta[layer_index][1:,:]#计算梯度值for layer_index in  range(num_layers-1):layer_delta = np.dot(delta[layer_index+1],layers_activations[layer_index].T)  #微调矩阵deltas[layer_index] = deltas[layer_index] + layer_delta #第一次25 * 785 第二次 10 * 26for layer_index in range(num_layers-1):deltas[layer_index] = deltas[layer_index] * (1/num_examples)return deltas@staticmethoddef cost_function(data,labels,thetas,layers):num_layers = len(layers)num_examples = data.shape[0]num_labels = layers[-1]#前向传播走一次predictions = MultilayerPerceptron.feedforword_propagation(data,thetas,layers)#制作标签,每一个样本的标签都是one-dotbitwise_labels = np.zeros((num_examples,num_labels))for example_index in range(num_examples):bitwise_labels[example_index][labels[example_index][0]] = 1#咱们的预测值是概率值y= 7 [0,0,0,0,0,0,1,0,0,0]    在正确值的位置上概率越大越好 在错误值的位置上概率越小越好bit_set_cost = np.sum(np.log(predictions[bitwise_labels == 1]))bit_not_set_cost = np.sum(np.log(1 - predictions[bitwise_labels == 0]))cost = (-1/num_examples) * (bit_set_cost+bit_not_set_cost)return cost@staticmethoddef feedforword_propagation(data,thetas,layers):num_layers = len(layers)num_examples = data.shape[0]in_layer_activation = data #输入层#逐层计算 隐藏层for layer_index in range(num_layers - 1):theta = thetas[layer_index]out_layer_activation = sigmoid(np.dot(in_layer_activation,theta.T)) #输出层# 正常计算之后是num_examples * 25 ,但是要考虑偏置项 变成num_examples * 26out_layer_activation = np.hstack((np.ones((num_examples,1)),out_layer_activation))in_layer_activation = out_layer_activation#返回输出层结果,不要偏置项return in_layer_activation[:,1:]@staticmethoddef thetas_roll(unrolled_theta,layers):num_layers = len(layers)thetas = {}unrolled_shift = 0for layer_index in range(num_layers - 1):in_count = layers[layer_index]out_count = layers[layer_index + 1]thetas_width = in_count + 1thetas_height = out_countthetas_volume = thetas_width * thetas_heightstart_index = unrolled_shiftend_index =unrolled_shift + thetas_volumelayer_theta_unrolled = unrolled_theta[start_index:end_index]thetas[layer_index] = layer_theta_unrolled.reshape((thetas_height,thetas_width))unrolled_shift = unrolled_shift + thetas_volumereturn thetas@staticmethoddef thetas_unroll(thetas):#拼接成一个向量num_theta_layers = len(thetas)unrolled_theta = np.array([])for theta_layer_index in range(num_theta_layers):unrolled_theta = np.hstack((unrolled_theta,thetas[theta_layer_index].flatten()))return unrolled_theta@staticmethoddef thetas_init(layers):num_layers = len(layers)thetas = {} #用字典形式 key:表示第几层 vlues:权重参数矩阵for layer_index in range(num_layers-1):'''会执行两次: 得到两组参数矩阵 25 * 785 , 10 * 26'''in_count = layers[layer_index]out_count = layers[layer_index+1]#初始化 初始值小#这里需要考虑偏置项,偏置的个数与输出的个数一样thetas[layer_index]=np.random.rand(out_count,in_count+1) * 0.05 #加一列输入特征return thetas

 五、手写数字识别

        数据集(读者可以找找下载,我就不放链接了>_<):   

 

         共一万个样本,第一列为标签值,一列表示像素点的值共28*28共784个像素点。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.image as mping
import math
from Neural_Network_Lab.Multilayer_Perceptron import MultilayerPerceptrondata = pd.read_csv('../Neural_Network_Lab/data/mnist-demo.csv')
#展示数据
numbers_to_display = 25
num_cells = math.ceil(math.sqrt(numbers_to_display))
plt.figure(figsize=(10,10))
for plot_index in range(numbers_to_display):digit = data[plot_index:plot_index+1].valuesdigit_label = digit[0][0]digit_pixels = digit[0][1:]image_size = int(math.sqrt(digit_pixels.shape[0]))frame = digit_pixels.reshape((image_size,image_size))plt.subplot(num_cells,num_cells,plot_index+1)plt.imshow(frame,cmap = 'Greys')plt.title(digit_label)
plt.subplots_adjust(wspace=0.5,hspace=0.5)
plt.show()train_data = data.sample(frac= 0.8)
test_data = data.drop(train_data.index)train_data = train_data.values
test_data = test_data.valuesnum_training_examples = 8000X_train = train_data[:num_training_examples,1:]
y_train = train_data[:num_training_examples,[0]]X_test = test_data[:,1:]
y_test = test_data[:,[0]]layers = [784,25,10]
normalize_data = True
max_iteration = 500
alpha = 0.1multilayerperceptron = MultilayerPerceptron(X_train,y_train,layers,normalize_data)
(thetas,cost_history) = multilayerperceptron.train(max_iteration,alpha)
plt.plot(range(len(cost_history)),cost_history)
plt.xlabel('Grident steps')
plt.ylabel('cost')
plt.show()y_train_predictions = multilayerperceptron.predict(X_train)
y_test_predictions = multilayerperceptron.predict(X_test)train_p = np.sum((y_train_predictions == y_train) / y_train.shape[0] * 100)
test_p = np.sum((y_test_predictions == y_test) / y_test.shape[0] * 100)print("训练集准确率:",train_p)
print("测试集准确率:",test_p)numbers_to_display = 64
num_cells = math.ceil(math.sqrt(numbers_to_display))
plt.figure(figsize=(15,15))
for plot_index in range(numbers_to_display):digit_label = y_test[plot_index,0]digit_pixels = X_test[plot_index,:]predicted_label = y_test_predictions[plot_index][0]image_size = int(math.sqrt(digit_pixels.shape[0]))frame = digit_pixels.reshape((image_size,image_size))plt.subplot(num_cells,num_cells,plot_index+1)color_map = 'Greens' if predicted_label == digit_label else 'Reds'plt.imshow(frame,cmap = color_map)plt.title(predicted_label)plt.tick_params(axis='both',which='both',bottom=False,left=False,labelbottom=False)plt.subplots_adjust(wspace=0.5,hspace=0.5)
plt.show()

         训练集8000个,测试集2000个,迭代次数500次

        

        

         这里准确率不高,读者可以自行调整参数,改变迭代次数,网络层次都可以哦。

          

        

         

        

        

       

        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/287331.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HarmonyOS网格布局:List组件和Grid组件的使用

简介 在我们常用的手机应用中&#xff0c;经常会见到一些数据列表&#xff0c;如设置页面、通讯录、商品列表等。下图中两个页面都包含列表&#xff0c;“首页”页面中包含两个网格布局&#xff0c;“商城”页面中包含一个商品列表。 上图中的列表中都包含一系列相同宽度的列表…

【Linux系统】进程概念创建进程进程标示符

什么是进程&#xff1f; 操作系统中&#xff0c; 进程可以同时存在非常多的。根据我们之前谈的操作系统具有“管理”的特性&#xff0c; 那么就有&#xff0c;既然要管理&#xff0c;就要 --- 先描述&#xff0c;在组织&#xff01;&#xff01;&#xff01; 由冯诺依曼体系结…

并发VS并行

参考文章 面试必考的&#xff1a;并发和并行有什么区别&#xff1f; 并发&#xff1a;一个人同时做多件事&#xff08;射击游戏队友抢装备&#xff09; 并行&#xff1a;多人同时处理同一件事&#xff08;射击游戏敌人同时射击对方&#xff09;

关于hook ntdll 代码详解

UNHOOK ntdll DWORD unhook() {//创建该结构体用于获取该dll的信息 将所有成员变量初始化为零MODULEINFO mi {};//获取当前内存的ntdll的句柄HMODULE ntdllModule GetModuleHandleA("ntdll.dll");//HANDLE(-1)表示获取当前进程的句柄 该函数用于获取该进程的信息G…

在项目中数据库如何优化?【MySQL主从复制(创建一个从节点复制备份数据)】【数据库读写分离ShardingJDBC(主库写,从库读)】

MySQL主从复制 MySQL主从复制介绍MySQL复制过程分成三步&#xff1a;1). MySQL master 将数据变更写入二进制日志( binary log)2). slave将master的binary log拷贝到它的中继日志&#xff08;relay log&#xff09;3). slave重做中继日志中的事件&#xff0c;将数据变更反映它自…

学点儿数据库_Day11_数据库简介、Sql单表、GROUP BY答疑

1 数据库简介 数据在内存&#xff1a; 优点&#xff1a;读写速度快 缺点&#xff1a;程序结束后数据丢失 保存到文件 优点&#xff1a;数据可以永久保存 缺点&#xff1a; 1、频繁的IO操作&#xff0c;效率不高 2、数据的管理非常不方便&#xff0c;需要把所有的数据整体都读…

云原生靶场kebernetesGoat、Metarget

靶场 文章目录 靶场kebernetesGoat靶场安装Docker in DockerSSRF漏洞容器逃逸到主系统Docker CIS 基线分析Kubernetes CIS 安全基线分析分析被部署挖矿软件的容器镜像获取环境信息Hidden in layersRBAC最低权限配置错误使用 Sysdig Falco 进行运行时安全监控和检测 Metarget ke…

C++类和对象、面向对象编程 (OOP)

文章目录 一、封装1.抽象、封装2.类和对象(0)学习视频(1)类的构成(2)三种访问权限(3)struct和class的区别(4)私有的成员变量、共有的成员函数(5)类内可以直接访问私有成员&#xff0c;不需要经过对象 二、继承三、多态1.概念2.多态的满足条件3.多态的使用条件4.多态原理剖析5.纯…

负氧离子监测站:创造健康生活环境

TH-FZ5在蓝天白云之下&#xff0c;那一座座高耸的全彩屏负氧离子监测站&#xff0c;如同一支支科技的绿芽&#xff0c;静静破土而出&#xff0c;为这片土地带来了新的生命力。这些现代化的设备不仅美化了环境&#xff0c;更是我们呼吸健康守护者&#xff0c;它们的存在让我们的…

初识云原生、虚拟化、DevOps

文章目录 K8S虚拟化DevOpsdevops平台搭建工具大数据架构 K8S master 主节点&#xff0c;控制平台&#xff0c;Master节点负责核心的调度、管理和运维&#xff0c;不需要很高性能&#xff0c;不跑任务&#xff0c;通常一个就行了&#xff0c;也可以开多个主节点来提高集群可用度…

Arduino+ESP8266+华为云物联网平台实现智能开关

前言 最近在做一个物联网项目&#xff0c;涉及到智能开关的开发。目前已经实现简单的TCP通信远程控制&#xff0c;但是考虑到后期的设备管理以及设备通信所需要的技术和服务器的维护成本&#xff0c;我决定将设备接入云平台。本文将详细阐述如何利用华为云的物联网平台&#x…

CI/CD实战-jenkins流水线 6

现最新版本没有该问题的出现 基于RBAC的身份授权&#xff1a; 安装插件&#xff1a; 新建测试用户 修改默认授权策略 新建的用户就没有任何权限 新建角色并授权 添加用户角色身份 pipeline 安装ssh agent插件 由于最新版的插件是有问题的&#xff0c;会有以下报错&#xff…

Memcached分布式内存对象数据库

一 Memcached 概念 Memcached 是一个高性能的分布式内存对象缓存系统&#xff0c;用于动态 Web 应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数&#xff0c;从而提高动态、数据库驱动网站的速度。 二 在架构中的位置 Memcached 处于前端或中间件后…

使用SM4国密加密算法对Spring Boot项目数据库连接信息以及yaml文件配置属性进行加密配置(读取时自动解密)

一、前言 在业务系统开发过程中&#xff0c;我们必不可少的会使用数据库&#xff0c;在应用开发过程中&#xff0c;数据库连接信息往往都是以明文的方式配置到yaml配置文件中的&#xff0c;这样有密码泄露的风险&#xff0c;那么有没有什么方式可以避免呢&#xff1f;方案当然是…

怎样从录制好的视频中提取音频?分离音频只需几秒 音频提取

在当今数字化的世界中&#xff0c;视频与音频的结合已经成为我们生活中不可或缺的一部分。然而&#xff0c;有时我们可能只需要视频中的音频部分&#xff0c;这时候&#xff0c;如何从视频中提取音频就成了一个实用且常见的问题。本文将详细介绍几种常见的方法&#xff0c;帮助…

设计用于驱动12 V汽车接地负载,VN5E160ASTR、VND5E160MJTR、VND5E025AKTR、VND5E050ACKTR 单/双通道高侧驱动器

摘要 意法半导体VIPower系列高侧开关符合汽车应用要求&#xff0c;内嵌先进的控制功能&#xff0c;其新型保护机制适用于各种负载类型及额定功率。 此类开关是汽车系统的理想选择&#xff0c;如&#xff1a;接线盒、内部/外部照明、直流电机驱动等&#xff0c;并适用于任何需…

java 企业工程管理系统软件源码+Spring Cloud + Spring Boot +二次开发+ 可定制化

工程项目管理软件是现代项目管理中不可或缺的工具&#xff0c;它能够帮助项目团队更高效地组织和协调工作。本文将介绍一款功能强大的工程项目管理软件&#xff0c;该软件采用先进的Vue、Uniapp、Layui等技术框架&#xff0c;涵盖了项目策划决策、规划设计、施工建设到竣工交付…

机器学习笔记(4)—逻辑回归(Logistic Regression)

文章目录 逻辑回归&#xff08;Logistic Regression&#xff09;分类问题假说表示判定边界代价函数简化的成本函数和梯度下降多类别分类&#xff1a;一对多 逻辑回归&#xff08;Logistic Regression&#xff09; 分类问题 分类问题中&#xff0c;我们要预测的变量 y y y是一…

Hive入门

什么是hive&#xff1f; - Hive是Facebook开发并贡献给Hadoop开源社区的。它是建立在 Hadoop体系架构上的一层 SQL抽象&#xff0c;使得数据相关人 员使用他们最为熟悉的SQL语言就可以进行海量数据的处理、 分析和统计工作 - Hive将数据存储于HDFS的数据文件映射为一张数据库…

【笔记】MJ Prompt

参数 --chaos 10 or --c 10, 0-10, defalut 0 --quality 1 or --q, 0.25-1, defalut 1 --iw 2, 0.5-2, --stylize 100 or --s 100, 0-1000, defalut 100 --cref URL --cw 100, 0-100stylize 风格化&#xff0c;MJ不同的出图模式&#xff0c;有默认的艺术风格&#xff0c;该值…