特征工程的力量

为什么你应该使用逻辑回归来建模非线性决策边界(使用 Python 代码)

作为一名大数据从业者,复杂的机器学习技术非常具有吸引力。使用一些深度神经网络 (DNN) 获得额外的 1% 准确率,并在此过程中启动 GPU 实例,这让人非常满意。然而,这些技术通常将思考留给计算机,让我们对模型的工作原理了解甚少。所以,我想回到基础知识。

在这里插入图片描述

在本文中,我希望教你一些关于特征工程的知识,以及如何使用它来建模非线性决策边界。我们将探讨两种技术的优缺点:逻辑回归(带有特征工程)和 NN 分类器。将提供用于拟合这些模型以及可视化其决策边界的 Python 代码。你可以在 Github1 上找到完整的项目代码。最后,我希望让你理解为什么特征工程可能是其他非线性建模技术的更好替代方案。

什么是特征工程

当你从原始数据创建特征或将现有特征的函数添加到数据集时,你就在进行特征工程。这通常使用特定领域的领域知识来完成2。例如,假设我们想要预测一个人从手术中恢复所需的时间(Y)。从之前的手术中,我们获得了患者的康复时间、身高和体重。根据这些数据,我们还可以计算出每个患者的 BMI = 身高/体重²。通过计算 BMI 并将其纳入数据集,我们正在进行特征工程。

我们为什么要进行特征工程

特征工程非常强大,因为它允许我们将非线性问题重新表述为线性问题。为了说明这一点,假设恢复时间与身高和体重有以下关系:

Y = β 0 + β 1 (高度) + β 2 (重量) + β 3 (高度 / 重 量 2 ) + 噪声 Y = \beta_0 + \beta_1(高度)+ \beta_2(重量)+ \beta_3(高度/重量^2)+ 噪声 Y=β0+β1(高度)+β2(重量)+β3(高度/2+噪声

查看第 3 项,我们可以看到 Y 与身高和体重没有线性关系。这意味着我们可能不会期望线性模型(例如线性回归)能够很好地估计 β 系数。你可以尝试使用非线性模型(例如 DNN),或者我们可以通过进行一些特征工程来帮助我们的模型。如果我们决定将 BMI 作为一个特征,则关系将变为:

Y = β 0 + β 1 (高度) + β 2 (重量) + β 3 ( B M I ) + 噪声 Y = \beta_0 + \beta_1(高度)+ \beta_2(重量)+ \beta_3(BMI)+ 噪声 Y=β0+β1(高度)+β2(重量)+β3BMI+噪声
Y 现在可以被建模为 3 个变量的线性关系。因此,我们期望线性回归能够更好地估计系数。稍后,我们将看到同样的想法也适用于分类问题。

为什么不让电脑来做这项工作

如果从技术角度来讲,特征工程本质上就是核心技巧,因为我们将特征映射到更高的平面3。尽管使用核技巧通常不需要太多思考。核函数被视为超参数,可以使用蛮力找到最佳函数——尝试大量不同的函数变体。使用正确的核函数,你可以建模非线性关系。给定正确数量的隐藏层 / 节点,DNN 还将自动构建特征的非线性函数2。那么,如果这些方法可以建模非线性关系,我们为什么还要费心进行特征工程呢?

我们上面解释了特征工程如何让我们即使在使用线性模型的情况下也能捕捉数据中的非线性关系。这意味着,根据问题的不同,我们可以实现与非线性模型类似的性能。我们将在本文后面详细介绍一个示例。除此之外,使用特征工程还有其他好处,这使得这项技术很有价值。

在这里插入图片描述

首先,你会更好地理解模型的工作原理。这是因为你确切地知道模型使用什么信息进行预测。此外,像逻辑回归这样的模型可以通过直接查看特征系数来轻松解释。第二个原因与第一个原因相符,即模型更容易解释。如果你在工业界工作,这一点尤其重要。你的同事也更有可能接触到一些更简单的模型。第三个原因是你的模型不太可能过度拟合训练数据。通过强制加载不同的超参数,很容易导致对数据中噪声建模。相比之下,有了深思熟虑的特征,你的模型将是直观的,并且很可能模拟真实的潜在趋势。

数据集

让我们深入研究一个实际的例子。为了尽可能清晰,我们将使用人工生成的数据集。为了避免这个例子太枯燥,我们将围绕它创建一个叙述。假设你的人力资源部门要求你创建一个模型来预测员工是否会晋升。该模型应该考虑员工的年龄和绩效分数。

我们在下面的代码中为 2000 名假设员工创建特征。员工的年龄可以在 18 到 60 岁之间。绩效分数可以在 -10 到 10 之间(10 为最高)。这两个特征都经过了打乱,因此它们不相关。然后我们使用以下年龄 (a) 和绩效 § 函数来生成目标变量:

γ ( a , p ) = 100 ( a ) + 200 ( p ) + 500 ( a / p ) − 10000 + 500 ( n o i s e ) \gamma(a,p)= 100(a)+ 200(p)+ 500(a / p)- 10000 + 500(noise) γap=100a+200p+500a/p10000+500noise

γ ( a , p ) ≥ 0 \gamma(a,p)≥ 0 γ(a,p)0 时,员工会得到晋升;当 $\gamma(a,p) < 0 $​时,员工不会得到晋升。我们可以看到,上面的函数中包含了 a/p 项。这意味着决策边界将不是年龄和绩效的线性函数。还包括随机噪声,因此数据不是完全可分离的。换句话说,模型不可能 100% 准确。

import numpy as np
import pandas as pdn_points = 2000age = np.round(np.linspace(18, 60, n_points), 2) # age of employee
np.random.shuffle(age) # shuffleperformance = np.linspace(-10, 10, n_points) # performance score of employee
np.random.shuffle(performance) # shufflenoise = np.random.randn(n_points)g = (100 * age) + 200 * (performance) + 500 * age / performance - 10000 + 500 * noise
y = [1 if y >= 0 else 0 for y in g]data = pd.DataFrame(data = {'age': age, 'performance': performance, 'y': y})print(sum(y))
data.head()---
474age		performance	y
0	53.32	-6.098049	0
1	32.10	-7.848924	0
2	58.72	9.709855	1
3	59.52	4.387194	1
4	28.55	7.418709	0

如果上述步骤有点令人困惑,请不要担心。我们可以通过使用以下代码可视化数据集来使事情变得更清晰。在这里,我们创建了数据的散点图,结果可以在图 1 中看到。仅通过两个特征,很容易准确地看到发生了什么。在 y 轴上,我们有员工的绩效分数,在 x 轴上,我们有员工的年龄。晋升员工的分数为红色,未晋升的员工分数为蓝色。最终,2000 名员工中有 459 名(23%)获得了晋升。对于不同的随机样本,该比例会略有变化。

plt.subplots(nrows = 1, ncols = 1, figsize = (15, 10))plt.scatter('age', 'performance', c = '#ff2121', s = 50, edgecolors = '#000000', data = data[data.y == 1])
plt.scatter('age', 'performance', c = '#2176ff', s = 50, edgecolors = '#000000', data = data[data.y == 0])
plt.ylabel('Performance Score', size = 20)
plt.xlabel('Age', size = 20)
plt.yticks(size = 12)
plt.xticks(size = 12)
plt.legend(['Promoted', 'Not Promoted'], loc = 2, prop = {'size': 20})
plt.savefig('../figures/article_feature_eng/figure1.png', format = 'png')

图 1:数据散点图

尽管这些数据是生成的,但我们仍然可以对该图做出现实的解释。在图 1 中,我们可以看到 3 个不同的员工组。第一个是绩效得分低于 0 的组。由于绩效不佳,这些员工中的大多数都没有得到晋升,我们还可以预期其中一些员工被解雇。我们可以预期得分高于 0 的员工要么得到晋升,要么接受其他公司的报价。得分特别高的员工往往会离开。这可能是因为他们的需求量很大,而且在其他地方得到了更好的报价。然而,随着雇主年龄的增长,他们需要更高的绩效分数才能离开。这可能是因为年长的员工在目前的职位上更舒服。

无论如何,很明显,决策边界不是线性的。换句话说,不可能画出一条直线来很好地区分晋升组和未晋升组。因此,我们不会指望线性模型能做得很好。让我们通过尝试仅使用两个特征(年龄和表现)来拟合逻辑回归模型来证明这一点。

逻辑回归

在下面的代码中,我们将 2000 名员工分成训练集(70%)和测试集(30%)。我们使用训练集来训练逻辑回归模型。然后,使用该模型,我们对测试集进行预测。测试集的准确率为 82%。这似乎不算太糟糕,但我们应该考虑到只有不到 23% 的员工获得了晋升。因此,如果我们只是猜测没有员工会得到晋升,那么我们应该预期准确率约为 77%。

from sklearn.model_selection import train_test_split
import sklearn.metrics as metric
import statsmodels.api as smx = data[['age', 'performance']]
x = sm.add_constant(x)
y = data['y']
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 2024)model = sm.Logit(y_train, x_train).fit() # fit logistic regression modelpredictions = np.around(model.predict(x_test))
accuracy = metric.accuracy_score(y_test, predictions)print(round(accuracy * 100, 2))---
Optimization terminated successfully.Current function value: 0.428402Iterations 7
81.83

通过使用以下代码可视化决策边界,我们可以更好地理解模型正在做什么。在这里,我们在样本空间内生成一百万个点。然后,我们使用逻辑回归模型对所有这些点进行预测。与图 1 中的散点图一样,我们可以绘制每个点。每个点的颜色由模型的预测决定 — 如果模型预测晋升,则为粉红色,否则为浅蓝色。这为我们提供了决策边界的良好近似值,可以在图 2 中看到。然后,我们可以在这些点上绘制实际数据集。

n_points = 1000000 # use many point to visualise decision boundryage_db = np.linspace(18, 60, n_points)
np.random.shuffle(age_db)performance_db = np.linspace(-10, 10, n_points)
np.random.shuffle(performance_db)data_db = pd.DataFrame({'age': age_db, 'performance': performance_db})
data_db = sm.add_constant(data_db)# make predictions on the decision boundry points
predictions = model.predict(data_db)
y_db = [round(p) for p in predictions]
data_db['y'] = y_dbfig, ax = plt.subplots(nrows = 1, ncols = 1, figsize = (15, 10))# Plot decision boundry
plt.scatter('age', 'performance', c = '#ffbdbd', s = 1, data = data_db[data_db.y == 1])
plt.scatter('age', 'performance', c = '#b0c4ff', s = 1, data = data_db[data_db.y == 0])# Plot employee data points
plt.scatter('age', 'performance', c = '#ff2121', s = 50, edgecolors = '#000000', data = data[data.y == 1])
plt.scatter('age', 'performance', c = '#2176ff', s = 50, edgecolors = '#000000', data = data[data.y == 0])
plt.ylabel('Performance Score', size = 20)
plt.xlabel('Age', size = 20)
plt.yticks(size = 12)
plt.xticks(size = 12)plt.savefig('../figures/article_feature_eng/figure2.png', format = 'png')

从决策边界来看,我们可以看到模型表现很糟糕。它预测会升职的员工中,大约有一半没有升职。然后,对于大多数获得晋升的员工,它预测他们没有获得晋升。请注意,决策边界是一条直线。这强调了逻辑回归是一个线性分类器。换句话说,该模型只能构建一个决策边界,它是你赋予它的特征的线性函数。此时,我们可能会想尝试不同的模型,但让我们看看是否可以使用特征工程来提高性能。

图2:逻辑回归模型的决策边界

具有特征工程的逻辑回归

首先,如下面的代码所示,我们添加了附加特征(即年龄与表现的比率)。从那时起,我们遵循与之前的模型相同的过程。训练测试分割是相同的,因为我们对 “random_state” 使用相同的值。最后,这个模型的准确率达到了 98%,这是一个显着的改进。

data['age_perf_ratio'] = age / performancex = data[['age', 'performance', 'age_perf_ratio']]
x = sm.add_constant(x)
y = data['y']x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 2024)model = sm.Logit(y_train, x_train).fit() # fit new logistic regression modelpredictions = np.around(model.predict(x_test))
accuracy = metric.accuracy_score(y_test, predictions)print(round(accuracy * 100, 2))---
Optimization terminated successfully.Current function value: 0.039001Iterations 17
98.17

该模型仍然只需要员工的年龄和绩效即可进行预测。这是因为附加特征是年龄和绩效的函数。这使我们能够以与以前相同的方式可视化决策边界。即通过在样本空间中的每个年龄-绩效点使用模型的预测。我们可以看到,在图 3 中,通过添加附加特征,逻辑回归模型能够对非线性决策边界进行建模。从技术上讲,这是年龄和绩效的非线性函数,但它仍然是所有 3 个特征的线性函数。

图 3:具有特征工程的逻辑回归模型的决策边界

使用逻辑回归的另一个好处是模型是可解释的。这意味着模型可以用人类的术语来解释4。换句话说,我们可以直接查看模型系数来了解其工作原理。我们可以在表 1 中看到模型特征的系数及其 p 值。我们不会讲得太详细,但系数可以让你根据晋升几率的变化来解释特征的变化5。如果特征具有正系数,则该特征值的增加会导致晋升几率的增加。

在这里插入图片描述

从表 1 可以看出,随着年龄的增长,获得晋升的可能性也会增加。另一方面,对于绩效,这种关系并不那么明显。绩效的提高也会降低年龄/绩效比率。这意味着,绩效提高对几率的影响取决于员工的年龄。这非常符合直觉,因为它与我们在散点图中看到的一致。在这种情况下,可能没有必要使用系数以这种方式解释模型。仅仅可视化决策边界就足够了,但是,随着我们增加特征数量,这样做变得更加困难。在这种情况下,模型系数是理解模型如何工作的重要工具。

同样,P 值也有助于我们对模型的理解。由于系数是统计估计值,因此具有一定的不确定性。换句话说,我们可以确定系数要么是正值,要么是负值。这一点非常重要,因为如果我们不能确定系数的符号,就很难用几率的变化来解释特征的变化。从表 1 中我们可以看出,所有系数在统计意义上都是显著的。这并不奇怪,因为我们是利用特征函数生成数据的。

总体而言,当我们生成数据时,上述分析非常简单。因为我们知道使用什么函数来生成数据,所以很明显,附加特征会提高模型的准确性。实际上,事情不会这么简单。如果你对数据没有很好的理解,你可能需要与人力资源部门的某个人交谈。他们可能会告诉你他们过去看到的任何趋势。否则,通过使用各种图表和汇总统计数据探索该数据,你可以了解哪些特征可能很重要。但是,假设我们不想做所有这些艰苦的工作。

神经网络

为了进行比较,我们使用非线性模型。在下面的代码中,我们使用 Keras 来拟合 NN。我们仅使用年龄和表现作为特征,因此 NN 的输入层的维度为 2。有 2 个隐藏层,分别有 20 个和 15 个节点。两个隐藏层都具有 relu 激活函数,输出层具有 sigmoid 激活函数。为了训练模型,我们使用 10 和 100 个 epoch 的批处理大小。训练集大小为 1400,这给了我们 14000 个步骤。最后,该模型在测试集上的准确率达到了 96%。这与逻辑回归模型的准确率略低,但是也相差不大,不过我们不必进行任何特征工程。

from keras.models import Sequential
from keras.layers import Densex = data[['age', 'performance']]
y = data['y']
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.3, random_state = 2024)model = Sequential()model.add(Dense(20, input_dim = 2, activation = 'relu'))
model.add(Dense(15, activation = 'relu'))
model.add(Dense(1, activation = 'sigmoid'))
model.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy'])model.fit(x_train, y_train, epochs = 100, batch_size = 10) # fit ANNaccuracy = model.evaluate(x_test, y_test)
print(round(accuracy[1] * 100, 2))---
Epoch 1/100
2024-06-30 22:31:06.692852: W tensorflow/core/platform/profile_utils/cpu_utils.cc:128] Failed to get CPU frequency: 0 Hz
2024-06-30 22:31:06.891137: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.
140/140 [==============================] - 3s 4ms/step - loss: 0.5638 - accuracy: 0.7393
...
Epoch 100/100
140/140 [==============================] - 1s 6ms/step - loss: 0.0943 - accuracy: 0.9543
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
2024-06-30 22:32:14.638250: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.
19/19 [==============================] - 1s 10ms/step - loss: 0.0848 - accuracy: 0.9617
96.17

通过查看图 4 中的 NN 决策边界,我们可以看出为什么它被认为是一种非线性分类算法。即使我们只给出了模型年龄和性能,它仍然能够构建非线性决策边界。因此,在一定程度上,模型已经为我们完成了艰苦的工作。你可以说模型的隐藏层已经自动完成了特征工程。那么,考虑到这个模型具有很高的准确性并且需要我们付出的努力较少,我们为什么还要考虑逻辑回归呢?

在这里插入图片描述

NN 的缺点是它只能解释。这意味着,与逻辑回归不同,我们不能直接查看模型的参数来了解其工作原理4。我们可以使用其他方法,但最终,理解 NN 的工作原理更加困难。向非技术人员(例如人力资源主管)解释这一点更加困难。这使得逻辑回归模型在行业环境中更有价值。

工业界和学术界都存在许多问题,其中大多数问题都比本文给出的示例更复杂。本文提出的方法显然不是解决所有这些问题的最佳方法。例如,如果你尝试进行图像识别,那么使用逻辑回归将无济于事。对于较简单的问题,逻辑回归和对数据的良好理解通常就是你所需要的。

参考


  1. 茶桁的公共文章项目库(2024 年),https://github.com/hivandu/public_articles ↩︎

  2. T. Hastie, R. Tibshirani, J. Friedman, The Elements of Statistical Learning [pg 150] (2017), https://web.stanford.edu/~hastie/ElemStatLearn/ ↩︎ ↩︎

  3. Statinfer, The Non-Linear Decision Boundary (2017), https://statinfer.com/203-6-5-the-non-linear-decision-boundary/ ↩︎

  4. R. Gall, Machine Learning Explainability vs Interpretability: Two concepts that could help restore trust in AI (2018), https://www.kdnuggets.com/2018/12/machine-learning-explainability-interpretability-ai.html ↩︎ ↩︎

  5. UCLA, How do I Interpret Odds Ratios in Logistic Regression? (2020), https://stats.idre.ucla.edu/stata/faq/how-do-i-interpret-odds-ratios-in-logistic-regression/ ↩︎

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

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

相关文章

【使用webrtc-streamer解析rtsp视频流】

webrtc-streamer WebRTC (Web Real-Time Communications) 是一项实时通讯技术&#xff0c;它允许网络应用或者站点&#xff0c;在不借助中间媒介的情况下&#xff0c;建立浏览器之间点对点&#xff08;Peer-to-Peer&#xff09;的连接&#xff0c;实现视频流和&#xff08;或&a…

了解 ZooKeeper:关键概念和架构

ZooKeeper 是一种分布式协调服务&#xff0c;广泛用于分布式系统中&#xff0c;用于维护配置信息、命名、同步和组服务。它最初由雅虎开发&#xff0c;现在是一个 Apache 项目&#xff0c;已成为许多大型分布式应用程序不可或缺的一部分。本文深入探讨 ZooKeeper 的关键概念和架…

【Android】Activity子类之间的区别

从底层往顶层的继承顺序依次是&#xff1a; Activity&#xff0c;最原始的Activity androidx.core.app.ComponentActivity&#xff0c;仅仅优化了一个关于KeyEvent的拦截问题&#xff0c;一般不继承这个类 androidx.activity.ComponentActivity&#xff0c;支持和Android Arc…

Spark Join优化案例:Join Key 远大于 Payload

在一个案例中&#xff0c;大表 100GB、小表 10GB&#xff0c;它们全都远超广播变量阈值&#xff08;默认 10MB&#xff09;。因为小表的尺寸已经超过 8GB&#xff0c;在大于 8GB 的数据集上创建广播变量&#xff0c;Spark 会直接抛出异常&#xff0c;中断任务执行&#xff0c;所…

C语言 求 n 个数的阶乘之和

求n个数的阶乘之和&#xff08;即求1&#xff01;2&#xff01;3&#xff01;…n!&#xff09; 这个程序读取用户输入的正整数 n&#xff0c;计算并输出 1! 2! 3! ... n! 的值。 #include <stdio.h>// 计算阶乘的函数 long factorial(int num) {long result 1;for…

恢复 IntelliJ IDEA 中消失的菜单栏

要恢复 IntelliJ IDEA 中消失的菜单栏&#xff0c;可以按照以下简单步骤操作&#xff1a; 使用快捷键打开搜索&#xff1a;首先&#xff0c;双击 Shift 键打开全局搜索对话框。 搜索“Menu”&#xff1a;在搜索框中输入 menu&#xff0c;然后从搜索结果中选择与“Main Menu”相…

python-基础篇-选择-是什么

文章目录 定义一&#xff1a;Python 条件语句跟其他语言基本一致的&#xff0c;都是通过一条或多条语句的执行结果&#xff08; True 或者 False &#xff09;来决定执行的代码块。1、什么是条件语句2、if 语句的基本形式3、if 语句多个判断条件的形式4、if 语句多个条件同时判…

次序统计量

内容来源 概率论与数理统计教程&#xff08;第三版&#xff09; 茆诗松 高等教育出版社 数理统计学导论&#xff08;原书第7版&#xff09; 机械工业出版社 定义 设 X 1 , X 2 , ⋯ , X n X_1,X_2,\cdots,X_n X1​,X2​,⋯,Xn​ 是来自连续分布的随机样本 此分布具有 p d f…

【机器学习】Python reversed 函数

目录&#xff1a; reversed()函数初探应用于列表和元组实战演练&#xff1a;山海经故事文本处理 Python中的内置函数——reversed()。 这个函数能够帮助你高效地处理序列类型数据&#xff0c;比如列表、元组、字符串等&#xff0c;通过它你可以轻松地反转这些序列中的元素顺…

JSON 简述与应用

1. JSON 简述 JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式&#xff0c;常用于客户端与服务器之间的数据传递。它基于JavaScript对象表示法&#xff0c;但独立于语言&#xff0c;可以被多种编程语言解析和生成。 1.1 特点 轻量级&#…

JS对数据类型的检测方式

1. typeof()对于基本数据类型没问题&#xff0c;遇到引用数据类型就不管用 console.log( typeof 666 ); // number console.log( typeof [1,2,3] ); // object 2. instanceof()只能判断引用数据类型&#xff0c;不能判断基本数据类型 console.log( [] instanceof Array ) // tr…

Unity--协程--Coroutine

Unity–协程–Coroutine 1. 协程的基本概念 基本概念:不是线程,将代码按照划分的时间来执行,这个时间可以是具体的多少秒,也可以是物理帧的时间,也可以是一帧的绘制结束的时间。 协程的写法&#xff1a;通过返回IEnumerator的函数实现&#xff0c;使用yield return语句暂停执…

Golang | Leetcode Golang题解之第205题同构字符串

题目&#xff1a; 题解&#xff1a; func isIsomorphic(s, t string) bool {s2t : map[byte]byte{}t2s : map[byte]byte{}for i : range s {x, y : s[i], t[i]if s2t[x] > 0 && s2t[x] ! y || t2s[y] > 0 && t2s[y] ! x {return false}s2t[x] yt2s[y] …

python 查找轮廓

在Python中&#xff0c;查找图像的轮廓通常使用OpenCV库。以下是一个简单的示例代码&#xff0c;展示了如何使用OpenCV来查找并绘制图像的轮廓&#xff1a; pythonimport cv2 import numpy as np# 读取图像 image cv2.imread(your_image.jpg, 0) # 请将your_image.jpg替换为您…

设备树下的 platform 驱动编写

设备树下的 platform 驱动编写 设备树下的 platform 驱动简介 platform 驱动框架分为总线、设备和驱动&#xff0c;其中总线不需要我们这些驱动程序员去管理&#xff0c;这个是 Linux 内核提供的&#xff0c;我们在编写驱动的时候只要关注于设备和驱动的具体实现即可。在没有…

《昇思25天学习打卡营第6天 | 函数式自动微分》

《昇思25天学习打卡营第6天 | 函数式自动微分》 目录 《昇思25天学习打卡营第6天 | 函数式自动微分》函数式自动微分简单的单层线性变换模型函数与计算图微分函数与梯度计算Stop Gradient 函数式自动微分 神经网络的训练主要使用反向传播算法&#xff0c;模型预测值&#xff0…

建站小记:迁移域名DNS到CloudFlare

CloudFlare一直有赛博菩萨之称&#xff0c;据说用它做DNS解析服务又快又好又免费&#xff0c;还能防DDOS攻击&#xff0c;并且可以提供页面访问统计功能。 正好我博客网页打开略卡顿&#xff0c;所以决定将自己的DNS解析迁移到CloudFlare。 1.登录CF控制台&#xff0c;添加自己…

LeetCode-刷题记录-二分法合集(本篇blog会持续更新哦~)

一、二分查找概述 二分查找&#xff08;Binary Search&#xff09;是一种高效的查找算法&#xff0c;适用于有序数组或列表。&#xff08;但其实只要满足二段性&#xff0c;就可以使用二分法&#xff0c;本篇博客后面博主会持续更新一些题&#xff0c;来破除一下人们对“只有有…

(已解决)Adobe Flash Player已不再受支持

文章目录 前言解决方案 前言 一般来说&#xff0c;很少遇到官方网站使用Adobe Flash Player来进行录用名单公示了。但是&#xff0c;今天就偏偏遇到一次&#xff0c; 用谷歌浏览器打不开&#xff0c; 点了没有反应&#xff0c;用其他的浏览器&#xff0c;例如windows自带的那…

Golang | Leetcode Golang题解之第207题课程表

题目&#xff1a; 题解&#xff1a; func canFinish(numCourses int, prerequisites [][]int) bool {var (edges make([][]int, numCourses)indeg make([]int, numCourses)result []int)for _, info : range prerequisites {edges[info[1]] append(edges[info[1]], info[0]…