手写数字识别(机器学习)

一:一对多分类方法(one-vs-all)

这里先上的代码,想看原理可以到代码下面。

在数据集中,y的取值为1~10,y=10表示当前数字为0

首先读取数据,并对数据进行切分。

import pandas as pd
import numpy as np
import matplotlibmatplotlib.use('tKAgg')
import matplotlib.pyplot as pltfile_path = "D:\\JD\\Documents\\大学等等等\\自学部分\\机器学习自学画图\\手写数字识别\\ex3data1.xlsx"
data = pd.read_excel(file_path)
row_X = data.iloc[:, :-1]
row_y = data.iloc[:, -1]
print(row_X.shape, row_y.shape)

(4999, 400) (4999,)

我们来看一下是否显示图像:

def plot_an_image(X):pick_one = np.random.randint(len(X))  # 使用len(X)确保随机选择的索引在数据范围内image = X.iloc[pick_one, :]plt.figure(figsize=(4, 4))  # 设置图像大小plt.imshow(image.values.reshape(20, 20).T, cmap='gray_r')  # image.values用于提取数据plt.xticks([])plt.yticks([])plt.show()  # 显示图像def plot_100_image(X):# 随机选择100个样本pick_100 = np.random.choice(len(X), 100, replace=False)# 创建一个8x8的图形和10x10的子图网格fig, axes = plt.subplots(nrows=10, ncols=10, figsize=(8, 8))# 确保axes是一个2D数组(10x10)axes = axes.flatten()for i, idx in enumerate(pick_100):image = X.iloc[idx, :]# 将图像数据显示到相应的子图中axes[i].imshow(image.values.reshape(20, 20).T, cmap='gray_r')axes[i].axis('off')  # 关闭坐标轴plt.tight_layout()  # 自动调整子图参数plt.show()

调用显示100个图片的函数:

plot_100_image(row_X)

构建模型:

def sigmoid(z):return 1 / (1 + np.exp(-z))def costFunction(theta, X, y, lamda):  # 损失函数,要求它最小A = sigmoid(X @ theta)  # 预测值first = y * np.log(A)  # 损失函数部分second = (1 - y) * np.log(1 - A)  # 损失函数部分reg = theta[1:] @ theta[1:] * lamda / (2 * len(X))  # 正则项return -np.sum(first + second) / len(X) + regdef gradient_reg(theta, X, y, lamda):''':param theta: 要训练的参数:param X:    数据集:param y:     结果集:param lamda:   正则化参数:return:'''reg = theta[1:] * lamda / len(X)reg = np.insert(reg, 0, values=0, axis=0)  # 正则项梯度(导数)first = (X.T @ (sigmoid(X @ theta) - y)) / len(X)  # 损失函数梯度(导数)return reg + firstX = np.insert(row_X, 0, values=1, axis=1)
y = row_y[:]def one_vs_all(X, y, lamda, K):''':param X: 数据集:param y:  真实值:param lamda: 正则化项参数:param K:    标签个数:return:'''n = X.shape[1]  # 维度theta_all = np.zeros((K, n))for i in range(1, K + 1):theta_i = np.zeros(n,)res = minimize(costFunction,x0=theta_i,args=(X, y == i, lamda),method='TNC',jac=gradient_reg)theta_all[i - 1, :] = res.xreturn theta_alllamda =1
K=10
theta_final = one_vs_all(X,y,lamda,K)
print((theta_final))def predict(X,theta_final):h = sigmoid(X@theta_final.T)h_argmax = np.argmax(h,axis=1)return h_argmax+1
y_pred = predict(X,theta_final)
acc = np.mean(y_pred==y)
print(acc)

[[-2.37986344e+00  0.00000000e+00  0.00000000e+00 ...  1.30436171e-03
  -7.36236836e-10  0.00000000e+00]
 [-3.18544317e+00  0.00000000e+00  0.00000000e+00 ...  4.45792974e-03
  -5.08241654e-04  0.00000000e+00]
 [-4.79780226e+00  0.00000000e+00  0.00000000e+00 ... -2.86754653e-05
  -2.47292717e-07  0.00000000e+00]
 ...
 [-7.98708564e+00  0.00000000e+00  0.00000000e+00 ... -8.95567756e-05
   7.21960016e-06  0.00000000e+00]
 [-4.57327215e+00  0.00000000e+00  0.00000000e+00 ... -1.33515788e-03
   9.98385662e-05  0.00000000e+00]
 [-5.40538138e+00  0.00000000e+00  0.00000000e+00 ... -1.16772407e-04
   7.89384343e-06  0.00000000e+00]]
0.9445889177835567

可以看到准确率为0.9445889177835567

这里大家可能不知道minimize函数。这里给大家讲一下:

minimize 函数是 SciPy 库中的一个优化函数,主要用于求解最优化问题。它能够找到给定目标函数的最小值,并返回对应的变量值。理解 minimize 函数的工作原理对于优化模型和算法至关重要。下面,我会详细讲解 minimize 函数的各个参数及其使用方法。

minimize 函数的参数详解

  1. fun:

    • 这是一个必须的参数,指定了需要最小化的目标函数。该函数必须接受参数并返回一个标量值(即目标函数的值)。
    • 在代码中,fun 是 costFunction。它计算了逻辑回归的代价(损失)函数,计算了预测值与真实值之间的误差以及正则化项。
  2. x0:

    • 初始猜测值。x0 是一个初始的变量值,用于开始优化过程。优化算法会从这些初始值出发,尝试找到使目标函数最小的最佳值。
    • 在代码中,x0 是 theta_i(初始化为全零向量)。它代表了逻辑回归模型的初始参数。
  3. args:

    • 这是一个元组,用于将额外的参数传递给目标函数。args 中的参数会被传递给 fun 函数。
    • 在你的代码中,args 是 (X, y == i, lamda),它将数据 X、标签的二值化结果 y == i 和正则化参数 lamda 传递给 costFunction
  4. method:

    • 指定使用的优化算法。SciPy 提供了多种优化算法,例如 'BFGS''Nelder-Mead''TNC''L-BFGS-B' 等等。
    • 在代码中,使用的是 'TNC'(Truncated Newton Conjugate Gradient)。这种方法适用于大规模问题,并在处理非线性优化时表现良好。
  5. jac:

    • 这是目标函数的梯度(即目标函数对各变量的偏导数)的函数。如果提供,minimize 会利用这些梯度信息来加速优化过程。
    • 在代码中,jac 是 gradient_reg,它计算了代价函数的梯度,包括正则化项的梯度。
  6. constraints:

    • 用于设置约束条件,通常用于优化问题中需要满足的条件(例如,变量的范围)。这是一个可选参数。
    • 代码中没有使用这个参数,因此可以忽略。
  7. bounds:

    • 用于设置每个变量的范围(例如,变量的上下界)。这是一个可选参数。
    • 代码中没有使用这个参数,因此在你的情况中可以忽略。
  8. tol:

    • 优化过程的容差。优化算法在达到设定的精度后停止。容差值越小,算法越精确,但计算可能更耗时。
    • 代码中没有设置,使用默认值。
  9. options:

    • 这个参数用于设置优化过程中的其他选项,例如最大迭代次数、输出选项等。
    • 代码中没有设置这个参数,使用默认值。

minimize 函数的工作流程

  1. 初始化:

    • minimize 函数首先使用 x0 作为初始值来开始优化过程。
  2. 计算目标函数:

    • 使用 fun 参数提供的函数来计算当前 x 值下的目标函数值。你的目标函数是 costFunction,它计算了逻辑回归的损失。
  3. 计算梯度:

    • 如果 jac 参数提供了梯度函数,minimize 会计算目标函数的梯度,这有助于加速优化过程。
  4. 选择优化算法:

    • minimize 根据 method 参数选择的优化算法来进行优化。优化算法会尝试逐步调整 x 的值,以找到使目标函数值最小的点。
  5. 迭代优化:

    • 优化算法会迭代地更新 x 的值,并计算目标函数和梯度,直到满足停止准则(如最大迭代次数或目标函数变化小于容差值)。
  6. 返回结果:

    • 优化完成后,minimize 返回一个包含最优解和其他信息的结果对象,包括最优参数 x、目标函数值、退出状态等。

假设你有一个简单的二次函数需要最小化,例如 f(x)=(x-3)^{2}

from scipy.optimize import minimize# 定义目标函数
def objective_function(x):return (x - 3)**2# 初始猜测值
x0 = [0]# 调用 minimize 函数
result = minimize(objective_function, x0)# 输出结果
print("最优解:", result.x)
print("目标函数值:", result.fun)

注意minimize要求参数的顺序,x0是objective_function的第一个参数。

假设我们有一个目标函数,目的是找到使得以下函数值最小化的 x:

f(x,a,b)=(x-a)^{2}+b

其中 a 和 b 是我们在计算函数值时需要用到的额外参数。假设 a 和 b 是已知的常数,我们希望优化 x

1. 定义目标函数

首先,我们定义目标函数 f。这个函数需要额外的参数 a 和 b

def objective_function(x, a, b):return (x - a)**2 + b

2. 传递额外参数

为了优化 x,我们需要将 a 和 b 传递给 objective_function。这里我们使用 scipy.optimize.minimize 函数,其中 args 参数用于传递这些额外的参数。

例如,我们希望将 a 设置为 5,b 设置为 2,初始值 x0 为 0。加上损失函数的梯度可能更快一些。

from scipy.optimize import minimize# 额外参数
a = 5
b = 2#定义目标函数导数(关于目标参数的梯度)
# 定义梯度函数
def gradient_function(x):return 2 * (x - a)# 初始猜测值
x0 = 0# 调用 minimize 函数
result = minimize(objective_function, x0, args=(a, b),method='TNC', jac=gradient_function)print("最优解:", result.x)
print("最小值:", result.fun)

3. 结果解释

  • objective_function: 我们定义的目标函数,计算 (x - a)^2 + b
  • x0: 优化算法的初始猜测值。
  • args=(a, b): 传递给目标函数的额外参数 a 和 b

通过上述代码,minimize 会自动调用 objective_function,并将 xa 和 b 传递给它。优化过程会在 x 上进行,以最小化目标函数的值。

这里一定要注意:当我们使用 minimize 函数时,args 中的参数顺序需要与目标函数定义中的顺序一致。例如,在上述目标函数中,args 应该按照 (a, b) 的顺序传递,因为目标函数期望 a 和 b 分别作为第二和第三个参数:

一对多原理

可能大家也不知道为什么要用“y == i”表达式。

大家应该理解二分类,如果上面是预测(“是”,“否”),那么X不变,y的值域为(“是”,“否”),只需要写成args=(X,y,lamda)就行了。

那如果有多个呢(假如有3个A,B,C)?我们是不是可以先预测A,讲A=1,BorC=0。这样以此类推。下面给出一些推理过程:

$y$为标签数组,其中$y$ 的每个元素表示样本的真实类别

我们要训练的类别是 i。例如,若 i = 1,则我们要训练一个模型来区分类别 1 和其他类别。

布尔数组 $y == i$ 生成一个表示每个样本是否属于类别 i的数组。数学上可以写作:

\text{label}_{i} = \begin{cases} 1 & \text{if } y_j = i \\ 0 & \text{if } y_j \neq i \end{cases}

代价函数 $J(\theta)$ 用于计算当前类别 i的分类误差,包括正则化项。可以表示为:

J(\theta) = -\frac{1}{m} \sum_{j=1}^m \left[ y_j \log(h(\mathbf{x}_j)) + (1 - y_j) \log(1 - h(\mathbf{x}_j)) \right] + \frac{\lambda}{2m} \sum_{k=1}^n \theta_k^2

 其中$h(\mathbf{x}_j) = \sigma(\mathbf{x}_j^T \theta)$ 是模型的预测概率,$\sigma$为 sigmoid 函数。

梯度$\nabla_\theta J(\theta)$的计算公式为:

\nabla_\theta J(\theta) = \frac{1}{m} \sum_{j=1}^m (h(\mathbf{x}_j) - y_j) \mathbf{x}_j + \frac{\lambda}{m} \theta

优化算法(例如梯度下降)用于最小化代价函数 $J(\theta)$,得到优化后的参数 $\theta$

\theta_{i} = \text{argmin}_{\theta} \left[ J(\theta) \right]

对于新的样本,使用优化后的参数进行预测:

\hat{y} = \text{argmax}_i \left( \text{softmax}(\mathbf{x} \cdot \theta_i^T) \right)

注意我们得到的\theta是一个矩阵:

       \begin{bmatrix} \theta_{1,1} & ... & \theta_{1,n} \\ \vdots &\vdots & \vdots \\ \theta_{10,1} & \cdots&\theta_{10,n} \end{bmatrix}

一共10行,每i行是对于第i个标签的判定。一行共有n个元素,对应着一条记录的n个特征。

通俗的说,第i行是用来预测这个记录属于i类标签的概率,因为一共有10类标签,所以每一记录都会训练10次,得出每一记录属于每一种标签的概率。(或者说,每一行都会训练一次所有的样本,属于这类标签的是正向,否则负向。最终得到每一类标签的权重参数)

注意:

X_{m\times n}\cdot \theta_{n \times 10} = M_{m \times 10}

这个M是结果。每一个记录都会有10列,找到每一列中最大的就是预测值。

def predict(X, theta_final):h = sigmoid(X @ theta_final.T)h_argmax = np.argmax(h, axis=1)return h_argmax + 1y_pred = predict(X, theta_final)
acc = np.mean(y_pred == y)
print(acc)

np.argmax(h, axis=1) 返回每行中最大值的索引。对于每个样本,h_argmax 是该样本最可能的类别的索引(从 0 开始)

h_argmax 返回的是类别索引(从 0 开始),所以需要加 1 将其转换为从 1 开始的类别标签。

二:Softmax方法

对于这个我上一篇文章有介绍原理

Softmax函数:

h_\theta(x)_k = \frac{e^{\theta_k^T x}}{\sum_{j=1}^K e^{\theta_j^T x}}

交叉熵损失度量的是预测的概率分布与实际标签之间的差异。对于样本 i和类别 k,交叉熵损失为:

-\left[ y_{i,k} \log(h_\theta(x_i)_k) \right]

当样本 i属于类别 k(即$y_{i,k} = 1$)时,损失函数为:

-\log(h_\theta(x_i)_k)

否则(即 $y_{i,k} = 0$),损失函数为 0。

将每个样本的损失求和得到总损失:

\text{Total Loss} = \sum_{i=1}^{m} \sum_{k=1}^{K} \left[ y_{i,k} \log(h_\theta(x_i)_k) \right]

为了得到每个样本的平均损失,最终的代价函数为:

J(\Theta) = -\frac{1}{m} \sum_{i=1}^{m} \sum_{k=1}^{K} \left[ y_{i,k} \log(h_\theta(x_i)_k) \right]

import pandas as pd
import numpy as np
import matplotlib
from scipy.optimize import minimizematplotlib.use('tkAgg')
import matplotlib.pyplot as pltfile_path = "D:\\JD\\Documents\\大学等等等\\自学部分\\机器学习自学画图\\手写数字识别\\ex3data1.xlsx"
data = pd.read_excel(file_path)
row_X = data.iloc[:, :-1]
row_y = data.iloc[:, -1]
print(row_X.shape, row_y.shape)def plot_an_image(X):pick_one = np.random.randint(len(X))  # 使用len(X)确保随机选择的索引在数据范围内image = X.iloc[pick_one, :]plt.figure(figsize=(4, 4))  # 设置图像大小plt.imshow(image.values.reshape(20, 20).T, cmap='gray_r')  # image.values用于提取数据plt.xticks([])plt.yticks([])plt.show()  # 显示图像def plot_100_image(X):# 随机选择100个样本pick_100 = np.random.choice(len(X), 100, replace=False)# 创建一个8x8的图形和10x10的子图网格fig, axes = plt.subplots(nrows=10, ncols=10, figsize=(8, 8))# 确保axes是一个2D数组(10x10)axes = axes.flatten()for i, idx in enumerate(pick_100):image = X.iloc[idx, :]# 将图像数据显示到相应的子图中axes[i].imshow(image.values.reshape(20, 20).T, cmap='gray_r')axes[i].axis('off')  # 关闭坐标轴plt.tight_layout()  # 自动调整子图参数plt.show()def softmax(z):e_z = np.exp(z - np.max(z, axis=1, keepdims=True))  # 稳定计算softmaxreturn e_z / np.sum(e_z, axis=1, keepdims=True)def costFunction(theta, X, y, lamda, K):m = X.shape[0]Theta = theta.reshape((K, X.shape[1]))  # 转换theta为K x n的矩阵A = softmax(X @ Theta.T)  # 计算预测值Y = np.eye(K)[y]  # one-hot 编码真实标签reg = lamda * np.sum(Theta[:, 1:] ** 2) / (2 * m)  # 正则项return -np.sum(Y * np.log(A)) / m + regdef gradient_reg(theta, X, y, lamda, K):m = X.shape[0]Theta = theta.reshape((K, X.shape[1]))A = softmax(X @ Theta.T)Y = np.eye(K)[y]grad = (A - Y).T @ X / mreg = lamda * np.concatenate([np.zeros((K, 1)), Theta[:, 1:]], axis=1) / mreturn (grad + reg).ravel()def one_vs_all(X, y, lamda, K):n = X.shape[1]  # 维度initial_theta = np.zeros((K * n,))res = minimize(costFunction,x0=initial_theta,args=(X, y, lamda, K),method='TNC',jac=gradient_reg)return res.x.reshape((K, n))def predict(X, theta_final):h = softmax(X @ theta_final.T)return np.argmax(h, axis=1)X = np.insert(row_X, 0, values=1, axis=1)  # 添加偏置项
y = row_y - 1  # 转换标签从1-10到0-9lamda = 1
K = 10
theta_final = one_vs_all(X, y, lamda, K)
print(theta_final)y_pred = predict(X, theta_final)
acc = np.mean(y_pred == y)
print(acc)

(4999, 400) (4999,)
[[ 6.02649610e-01  0.00000000e+00  0.00000000e+00 ...  1.10517407e-03
  -3.37000911e-10  0.00000000e+00]
 [ 1.60407084e-01  0.00000000e+00  0.00000000e+00 ...  2.69379180e-03
  -3.10863107e-04  0.00000000e+00]
 [-1.01989081e+00  0.00000000e+00  0.00000000e+00 ... -1.40438599e-04
   1.22128124e-07  0.00000000e+00]
 ...
 [-3.11440704e+00  0.00000000e+00  0.00000000e+00 ... -1.46182140e-04
   8.23433590e-06  0.00000000e+00]
 [-3.81197348e-01  0.00000000e+00  0.00000000e+00 ... -1.62596349e-03
   1.21163807e-04  0.00000000e+00]
 [-1.26535166e+00  0.00000000e+00  0.00000000e+00 ... -7.32969625e-05
   7.50789066e-06  0.00000000e+00]]
0.9623924784956991

可以看到这个比上面的准确率要高。

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

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

相关文章

【BUG】已解决:IndexError: positional indexers are out-of-bounds

IndexError: positional indexers are out-of-bounds 目录 IndexError: positional indexers are out-of-bounds 【常见模块错误】 【解决方案】 原因分析 解决方法 示例代码 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页,我是博…

JavaScript:数组排序(冒泡排序)

目录 一、数组排序 二、sort()方法 1、基本语法 2、默认排序 3、自定义排序 三、冒泡排序 1、基本概念 2、实现步骤 3、过程解析 4、代码示例 5、时间复杂度 一、数组排序 对一个给定数组进行处理,使其从无序变为有序,这个过程就是数组排序&…

二叉树基础及实现(二,加经典OJ)

目录: 一 .接引二叉树(一) 二 .二叉树相关oj题: 1. 检查两颗树是否相同 2. 另一颗树的子树 3. 翻转二叉树 4. 判断一颗二叉树是否是平衡二叉树 5. 对称二叉树 6. 二叉树的构建及遍历 7. 二叉树的分层遍历 8. 给定一个二叉树, 找到该树中两个指定节点的最…

Fine-BI学习笔记

官方学习文档:快速入门指南- FineBI帮助文档 FineBI帮助文档 (fanruan.com) 1.零基础入门 1.1 功能简介 完成四个流程:新建分析主题、添加数据、分析数据、分享协作。 示例数据获取:5分钟上手FineBI - FineBI帮助文档 (fanruan.com) 1.2 …

R语言优雅的进行广义可加模型泊松回归分析

泊松回归(Poisson regression)是以结局变量为计数结果时的一种回归分析。泊松回归在我们的生活中应用非常广泛,例如:1分钟内过马路人数,1天内火车站的旅客流动数,1天内的银行取钱人数,一周内的销…

【已解决】如何使用母版视图统一PPT格式?

母版视图在PPT中是一个强大的工具,可以帮助我们统一幻灯片的格式、布局和设计风格。今天来看看如何利用母版视图统一PPT格式,让每张幻灯片看起来一致和专业。 第一步:打开母版视图 打开PPT后,在顶部菜单栏中,选择【视…

Docker容器限制内存与CPU使用

文章目录 Docker 容器限制内存与 CPU 使用内存限额内存限制命令举例使用 `nginx` 镜像学习内存分配只指定 `-m` 参数的情况CPU 限制命令举例验证资源使用Docker 容器限制内存与 CPU 使用 在生产环境中,为了保证服务器不因某一个软件导致服务器资源耗尽,我们会限制软件的资源…

windows服务器启动apache失败,提示请通过cmd命令行启动:net start apache

Windows Server 2012 R2服务器突然停止运行apche,启动apache失败,提示请通过cmd命令行启动:net start apache 1.报错截图: 进入服务里输入命令启动也不行,提示由于登录失败而无法启动服务。 2.问题原因: 服务器www用…

Node.js知识点总结

Node.js知识点总结 Node.js其本质和浏览器一样是一个JavaScript运行环境。浏览器的运行环境为V8引擎浏览器内置API(BOM、DOM、Canvas);而node.js的运行环境是V8引擎node提供的API(fs、path、http)。它使JavaScript可以编写后端。 基本知识 fs文件系统模块 它提供一…

springboot宠物相亲平台-计算机毕业设计源码16285

目 录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2 开发环境及相关技术介绍 2.1 MySQL数据库的介绍 2.2 B/S架构的介绍 2.3 Java语言 2.4 SpringBoot框架 3 宠物相亲平台系统分析 3.1 可行性分析 3.1.1 技术可行性分析 3.1.2 经济…

基于FPGA + Qt + OpenCv的人脸考勤系统

一:界面设计 客户端界面设计: 服务端界面设计: 简介:首先服务端在注册界面先注册人脸,然后客户端界面进行人脸识别,将人脸识别的图像发送给服务端以后,服务端在图像数据库里寻找人脸比对,若有数据就将查询到的个人信息发送给客户端,并在客户端显示,查询界面是用来查…

Ribbon负载均衡与内核原理

什么是Ribbon? 目前主流的负载方案分为两种: 集中式负载均衡,在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如F5),也有软件的(Nginx)客户端根据自己的请求做负…

开放式耳机哪种性价比高?五大高口碑优质款式耳机直入!

​或许我们的日常生活中充满了噪声,例如马路、地铁还有公交上,嘈杂的声音会影响我们的心情,同时还会损伤我们的耳朵,在嘈杂的环境中,想听歌想煲剧了怎么办,又不想沉浸在自己的世界里,就可以使用…

rk3588s 定制版 USB adb , USB2.0与USB3.0 区别,adb 由typeC 转换到USB3.0(第二部分)

硬件资源: rk3588s 核心板定制的地板 软件资源: 网盘上的 android12 源码 1 硬件上 客户只想使用 type c 接口中的 usb2.0 OTG 。在硬件上,甚至连 CC芯片都没有连接。 关于一些前置的知识。 1 USB2.0 与 USB3.0 的区别。 usb3.0 兼容2.0 …

【北京迅为】《i.MX8MM嵌入式Linux开发指南》-第三篇 嵌入式Linux驱动开发篇-第四十九章 平台总线总结回顾

i.MX8MM处理器采用了先进的14LPCFinFET工艺,提供更快的速度和更高的电源效率;四核Cortex-A53,单核Cortex-M4,多达五个内核 ,主频高达1.8GHz,2G DDR4内存、8G EMMC存储。千兆工业级以太网、MIPI-DSI、USB HOST、WIFI/BT…

EEtrade:现货黄金盈利计算方法

现货黄金交易作为一种极具吸引力的投资方式,其盈利计算涉及多个关键因素,投资者需深入理解这些因素,才能准确评估交易结果,并制定科学的投资策略。 一、现货黄金基本盈利计算: 利润公式: 利润 (收盘价 -…

深入浅出mediasoup—WebRtcTransport

mediasoup 提供了多种 transport,包括 WebRtcTransport、PipeTransport、DirectTransport、PlainTransport 等,用来实现不同目的和场景的媒体通信。WebRtcTransport 是 mediasoup 实现与 WebRTC 客户端进行媒体通信的对象,是 mediasoup 最重要…

如何学习Airflow:糙快猛的大数据之路(附思维导图)

什么是Airflow? 在开始之前,让我们先简单了解一下Airflow是什么。Apache Airflow是一个开源的工作流管理平台。它允许你以代码的方式定义、调度和监控复杂的数据处理管道。 想象一下,你有一系列需要按特定顺序执行的任务,而且这些任务之间还有依赖关系,Airflow就是为解决这…

SpringBoot自动配置(面试重点)

自动配置是指: 自动配置是指在应用程序启动时,SpringBoot根据classpath路径下的jar包自动配置应用程序所需的一系列bean和组件,从而减少开发者的配置工作,提高开发效率。 一:Condition Condition是spring4.0之后添加…

linux离线安装mysql8(单机版)

文章目录 一、检查服务器是否有残留mysql资源,有的话就全删除1.1、查询mysql已安装的相关依赖:1.2、查找含有MySQL的目录 二、安装2.1、上传mysql安装包到文件夹下并解压2.2、移动及重命名2.3、mysql用户2.4、配置mysql所需的my.cnf文件2.5、给my.cnf配置…