深度学习算法原理实现——线性分类器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | import numpy as np import tensorflow as tf import matplotlib.pyplot as plt def model(inputs): return tf.matmul(inputs, W) + b def square_loss(targets, predictions): per_sample_losses = tf.square(targets - predictions) return tf.reduce_mean(per_sample_losses) learning_rate = 0.1 def training_step(inputs, targets): with tf.GradientTape() as tape: predictions = model(inputs) loss = square_loss(targets, predictions) grad_loss_wrt_W, grad_loss_wrt_b = tape.gradient(loss, [W, b]) W.assign_sub(grad_loss_wrt_W * learning_rate) b.assign_sub(grad_loss_wrt_b * learning_rate) return loss num_samples_per_class = 1000 negative_samples = np.random.multivariate_normal( mean = [ 0 , 3 ], cov = [[ 1 , 0.5 ],[ 0.5 , 1 ]], size = num_samples_per_class) positive_samples = np.random.multivariate_normal( mean = [ 3 , 0 ], cov = [[ 1 , 0.5 ],[ 0.5 , 1 ]], size = num_samples_per_class) inputs = np.vstack((negative_samples, positive_samples)).astype(np.float32) targets = np.vstack((np.zeros((num_samples_per_class, 1 ), dtype = "float32" ), np.ones((num_samples_per_class, 1 ), dtype = "float32" ))) plt.scatter(inputs[:, 0 ], inputs[:, 1 ], c = targets[:, 0 ]) plt.show() input_dim = 2 output_dim = 1 W = tf.Variable(initial_value = tf.random.uniform(shape = (input_dim, output_dim))) b = tf.Variable(initial_value = tf.zeros(shape = (output_dim,))) for step in range ( 40 ): loss = training_step(inputs, targets) print (f "Loss at step {step}: {loss:.4f}" ) predictions = model(inputs) plt.scatter(inputs[:, 0 ], inputs[:, 1 ], c = predictions[:, 0 ] > 0.5 ) plt.show() x = np.linspace( - 1 , 4 , 100 ) y = - W[ 0 ] / W[ 1 ] * x + ( 0.5 - b) / W[ 1 ] plt.plot(x, y, "-r" ) plt.scatter(inputs[:, 0 ], inputs[:, 1 ], c = predictions[:, 0 ] > 0.5 ) plt.show() |
效果图:
【代码分析】
这段代码实现了一个简单的线性分类器,用于二分类问题。主要使用了 TensorFlow 库进行实现。
以下是代码的主要部分和它们的功能:
1. 定义模型:model 函数定义了一个线性模型,输入乘以权重 W 加上偏置 b。
2. 定义损失函数:square_loss 函数定义了平方损失函数,计算目标值和预测值之间的差的平方的均值。
3. 定义训练步骤:training_step 函数定义了一步训练过程,包括前向传播、计算损失、反向传播和更新权重。
4. 生成训练数据:生成了两类样本,每类样本1000个,分别从两个二维正态分布中采样。
5. 初始化模型参数:初始化了权重 W 和偏置 b。
6. 训练模型:进行了40轮训练,每轮训练都会计算损失并更新权重。
7. 测试模型:使用训练数据对模型进行了测试,并绘制了分类结果。
8. 绘制决策边界:计算了决策边界的方程,并在图中绘制了决策边界。
这段代码的主要目的是展示如何使用 TensorFlow 实现一个简单的线性分类器,并用它进行二分类问题的训练和测试。
【该分类器和svm的区别】
这个线性分类器和支持向量机(SVM)都是用于进行二分类任务的模型,但它们在模型构造和优化目标上有一些不同:
1. 模型构造:这个线性分类器是一个简单的线性模型,它直接将输入特征与权重相乘,然后加上偏置,得到预测结果。而 SVM 不仅包括线性 SVM,还有非线性 SVM,非线性 SVM 通过使用核函数将输入特征映射到高维空间,然后在高维空间中找到最优的分割超平面。
2. 优化目标:这个线性分类器使用的是平方损失函数,优化目标是最小化预测值与真实值之间的平方差。而 SVM 使用的是合页损失函数,优化目标是最大化分类间隔,即找到一个超平面使得距离超平面最近的样本点(支持向量)到超平面的距离最大。
3. 决策边界:这个线性分类器的决策边界是由所有样本共同决定的,每个样本的改变都可能影响决策边界。而 SVM 的决策边界只由支持向量决定,非支持向量的样本即使有所改变,也不会影响决策边界。
4. 鲁棒性:由于 SVM 只关注支持向量,因此对于噪声和异常值具有较好的鲁棒性。而这个线性分类器由于使用的是平方损失函数,对于远离决策边界的样本(可能是噪声或异常值)会给予较大的权重,因此鲁棒性较差。
总的来说,这个线性分类器和 SVM 在一些基本概念上是相似的,但在具体的实现和优化目标上有所不同。
我们看下预测predictions的值:
1 2 3 4 5 6 7 8 | tf.Tensor( [[ - 0.09647062 ] [ 0.16270795 ] [ 0.2278583 ] ... [ 1.1228456 ] [ 1.0326965 ] [ 0.79803073 ]], shape = ( 2000 , 1 ), dtype = float32) |
可以看到,类似一个回归,而不是严格的分类(结果为0和1)!
还记得svm的预测代码吗?
1 2 3 4 5 | def predict( self , X): return self .h(X, self .w, self .b) def h( self , X, w, b): return np.sign(np.dot(w.T, X.T) + b).astype( int ) |
详见:机器学习算法原理实现——跟着gpt学习svm求解的SMO算法
为了对比和使用原生keras的效果,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | import numpy as np import tensorflow as tf import matplotlib.pyplot as plt def model(inputs): return tf.matmul(inputs, W) + b def square_loss(targets, predictions): per_sample_losses = tf.square(targets - predictions) return tf.reduce_mean(per_sample_losses) learning_rate = 0.1 def training_step(inputs, targets): with tf.GradientTape() as tape: predictions = model(inputs) loss = square_loss(targets, predictions) grad_loss_wrt_W, grad_loss_wrt_b = tape.gradient(loss, [W, b]) W.assign_sub(grad_loss_wrt_W * learning_rate) b.assign_sub(grad_loss_wrt_b * learning_rate) return loss num_samples_per_class = 1000 negative_samples = np.random.multivariate_normal( mean = [ 0 , 3 ], cov = [[ 1 , 0.5 ],[ 0.5 , 1 ]], size = num_samples_per_class) positive_samples = np.random.multivariate_normal( mean = [ 3 , 0 ], cov = [[ 1 , 0.5 ],[ 0.5 , 1 ]], size = num_samples_per_class) inputs = np.vstack((negative_samples, positive_samples)).astype(np.float32) targets = np.vstack((np.zeros((num_samples_per_class, 1 ), dtype = "float32" ), np.ones((num_samples_per_class, 1 ), dtype = "float32" ))) plt.scatter(inputs[:, 0 ], inputs[:, 1 ], c = targets[:, 0 ]) plt.show() input_dim = 2 output_dim = 1 W = tf.Variable(initial_value = tf.random.uniform(shape = (input_dim, output_dim))) b = tf.Variable(initial_value = tf.zeros(shape = (output_dim,))) for step in range ( 40 ): loss = training_step(inputs, targets) print (f "Loss at step {step}: {loss:.4f}" ) predictions = model(inputs) plt.scatter(inputs[:, 0 ], inputs[:, 1 ], c = predictions[:, 0 ] > 0.5 ) print (predictions) plt.show() x = np.linspace( - 1 , 4 , 100 ) y = - W[ 0 ] / W[ 1 ] * x + ( 0.5 - b) / W[ 1 ] plt.plot(x, y, "-r" ) plt.scatter(inputs[:, 0 ], inputs[:, 1 ], c = predictions[:, 0 ] > 0.5 ) plt.show() import numpy as np import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Dense from tensorflow.keras.optimizers import SGD import matplotlib.pyplot as plt def square_loss(y_true, y_pred): return tf.reduce_mean(tf.square(y_true - y_pred)) # 定义模型 model = Sequential([ Dense( 1 , input_dim = 2 , activation = None ) ]) model. compile (optimizer = SGD(learning_rate = 0.1 ), loss = square_loss) # 编译模型 # model.compile(optimizer=SGD(learning_rate=0.1), loss='mse') # 训练模型 model.fit(inputs, targets, epochs = 40 , batch_size = len (inputs)) # 测试模型 predictions = model.predict(inputs) # 绘制结果 plt.scatter(inputs[:, 0 ], inputs[:, 1 ], c = predictions[:, 0 ] > 0.5 ) plt.show() # 获取权重和偏置 weights, biases = model.layers[ 0 ].get_weights() # 打印权重和偏置 print ( "Weights:\n" , weights) print ( "Biases:\n" , biases) print ( "Customized model weight:" , W, "b:" , b) |
输出:
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2021-10-08 洞见RSA 2021|网络威胁狩猎——回归“乐趣”
2021-10-08 威胁狩猎语言 Kestrel 使用
2020-10-08 计算机原理系列之八 ——– 可执行文件的PLT和GOT 帮助你深刻理解libc库函数调用的细节(动态库)