首页 > 编程语言 >深度学习算法原理实现——线性分类器

深度学习算法原理实现——线性分类器

时间:2023-11-17 15:05:34浏览次数:35  
标签:loss plt inputs 分类器 tf 算法 np samples 线性

 

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

【代码分析】

这段代码实现了一个简单的线性分类器,用于二分类问题。主要使用了 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的值:

tf.Tensor(
[[-0.09647062]
 [ 0.16270795]
 [ 0.2278583 ]
 ...
 [ 1.1228456 ]
 [ 1.0326965 ]
 [ 0.79803073]], shape=(2000, 1), dtype=float32)

  

可以看到,类似一个回归,而不是严格的分类(结果为0和1)!

还记得svm的预测代码吗?

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的效果,如下:

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)

  

输出:

Weights:

 [[ 0.18331909]

 [-0.11702461]]

Biases:

 [0.36755753]

Customized model weight: <tf.Variable 'Variable:0' shape=(2, 1) dtype=float32, numpy=

array([[ 0.18086615],

       [-0.11948624]], dtype=float32)> b: <tf.Variable 'Variable:0' shape=(1,) dtype=float32, numpy=array([0.37705055], dtype=float32)>

二者的w和b基本上没有差别!

 



标签:loss,plt,inputs,分类器,tf,算法,np,samples,线性
From: https://blog.51cto.com/u_11908275/8447590

相关文章

  • 深度学习算法原理实现——自写神经网络识别mnist手写数字和训练模型
    代码来自:https://weread.qq.com/web/reader/33f32c90813ab71c6g018fffkd3d322001ad3d9446802347《python深度学习》fromtensorflow.keras.datasetsimportmnistfromtensorflow.kerasimportoptimizersimporttensorflowastfimportnumpyasnpclassNaiveDense:d......
  • 线性表A,B顺序存储合并
    7-1线性表A,B顺序存储合并有两张非递增有序的线性表A,B,采用顺序存储结构,两张表合并用c表存,要求C为非递减有序的,然后删除C表中值相同的多余元素。元素类型为整型#include<iostream>#include<cstring>usingnamespacestd;typedefstructf{intdata;f*next;}node,*......
  • 算法学习笔记(1):CDQ分治
    CDQ分治对比普通分治把一种问题划分成不同子问题,递归处理子问题内部的答案,再考虑合并子问题的答案。再看CDQ分治有广泛的应用,但我不会。但在接下来的题目体会到大概:将可能产生的对于答案的贡献分为两类:\(f(l,mid)\)与\(f(mid+1,r)\)内部产生的贡献,其贡献已在递......
  • 线性回归
    线性回归是一种用于建模和分析两个变量之间关系的统计方法。在简单线性回归中,我们考虑一个自变量(输入特征)和一个因变量(输出目标)之间的线性关系。这个关系可以表示为一条直线,其方程可以用来预测因变量的值。以下是线性回归的基本步骤和概念:问题定义:确定问题,并明确自变量和因变......
  • 字符串哈希算法
    一、字符串哈希:将一串字符串映射成一个整数,并用它来代替字符串进行比较。这样俩个字符串的比较就变成俩个整数的比较,可以将时间复杂度减少至O(1)二、哈希函数:为了将字符串转化为整数,需要一个哈希函数hash,使得以下条件成立:如果字符串s==t那么hash(s)==hash(t)。一般情况下采......
  • 数组类算法题——合并非递减数组
    合并非递减数组题目:给你两个按非递减顺序排列的整数数组nums1和nums2,另有两个整数m和n,分别表示nums1和nums2中的元素数目。请你合并nums2到nums1中,使合并后的数组同样按非递减顺序排列。注意:最终,合并后数组不应由函数返回,而是存储在数组nums1中。为了应......
  • 区间树上查找所有与给定区间相交的区间-算法复杂度正确性证明
    区间树是在平衡树上维护的数据结构,按照左端点大小排序。详见《算法导论》。算法设计思路红黑树的拓展在红黑树上维护结点属性\(min,max\):\(min\)表示该结点及其所有后代结点中的区间低端的最小值。\(max\)表示该结点及其所有后代结点中的区间高端的最大值。在插入时,对结点......
  • Dijkstra算法
    Dijkstra算法1.算法基本介绍Dijkstra算法是一个基于「贪心」、「广度优先搜索」、「动态规划」求一个图中一个点到其他所有点的最短路径的算法,时间复杂度O(n2)。Dijkstra算法通常是求解单源最短路中最快的算法,但它无法处理存在负权边的情况(原因在正确性证明中)。Dijkstra本质......
  • 最小生成树(Kruskal和Prim算法)
    最小生成树(Kruskal和Prim算法)部分资料来源于:最小生成树(Kruskal算法)_kruskal算法求最小生成树-CSDN博客、【算法】最小生成树——Prim和Kruskal算法-CSDN博客关于图的几个概念定义:连通图:在无向图中,若任意两个顶点vi与vj都有路径相通,则称该无向图为连通图。强连通图:在有向图中,若......
  • 数据结构C语言之线性表
    发现更多计算机知识,欢迎访问Cr不是铬的个人网站1.1线性表的定义线性表是具有相同特性的数据元素的一个有限序列对应的逻辑结构图形:从线性表的定义中可以看出它的特性:(1)有穷性:一个线性表中的元素个数是有限的(2)一致性:一个线性表中所有元素的性质相同,即数据类型相同(3)序列性:各......