在本系列的 上一篇文章 中，我们用 TensorFlow 构建了第一个神经网络，然后还通过 Keras 接触了第一个数据集。在本系列的第七篇文章中，我们将继续探索神经网络，并使用数据集来训练模型。我们还将介绍另一个强大的机器学习 Python 库 scikit-learn。不过在进入正题之前，我要介绍两个轰动性的人工智能应用：ChatGPT 和 DALL-E 2。（LCTT 译注：此文原文发表于 2023 年初，恰值以 ChatGPT 为代表的 AI 热潮开始掀起。）OpenAI 是一个人工智能研究实验室，它在人工智能和机器学习领域做了很多研究。 埃隆·马斯克 Elon Musk 是该组织的联合创始人之一。2022 年 11 月，该实验室推出了一款名为 ChatGPT 的在线工具。它是一个可以像人类一样聊天的人工智能聊天机器人。它是使用监督学习和强化学习技术训练的 大型语言模型 large language model （LLM）。ChatGPT 使用了 OpenAI 的 GPT-3.5 语言模型，这是 GPT-3（ 生成式预训练变换器 Generative Pre-trained Transformer ）的改进版本，GPT-3 是一种使用深度学习来生成类似人类文本的语言模型。（LCTT 译注：OpenAI 已于 2023 年 3 月 14 日 发布了 GPT-4.0，它支持图文混合的输入输出，并大幅提升了推理能力和准确性。）我仍然记得第一次使用 ChatGPT 时的兴奋。它清楚地展现了人工智能的能力。ChatGPT 的回答质量很高，通常与人类给出的答案没有区别。你可以使用它来纠正语法错误、改写句子、总结段落、编写程序等。实际上，我就用 ChatGPT 改写了本文中的许多句子。此外，我还故意使用有语法错误的文本测试了 ChatGPT，它纠正后的句子非常准确。它重新措辞和总结段落的能力也很惊人。程序员甚至有可能使用 ChatGPT 在短时间内解决编程难题。在 编程探险挑战赛 2022 Advent of Code 2022 中，就有人这样宣称（LCTT 译注：比赛官方只是没有完全禁止使用人工智能作为辅助，但是并不很推崇这样的作法。消息来源）。事实上在 2022 年 12 月，也就是 ChatGPT 发布的一个月后，Stack Overflow 发布了一条新的规定，禁止提交 GPT 或 ChatGPT 生成答案。（LCTT 译注：消息来源：Temporary policy Generative AI (e.g., ChatGPT) is banned - Meta Stack Overflow）图 1 显示了 ChatGPT 编写的将两个矩阵相加的 Python 程序。我要求用 BASIC、FORTRAN、Pascal、Haskell、Lua、Pawn、C、c++、Java 等语言编写程序，ChatGPT 总能给出答案，甚至对于像 Brainfuck 和 Ook! 这样生僻的编程语言也是如此。我很确定 ChatGPT 没有从互联网上复制程序代码。更确切地说，我认为 ChatGPT 是基于对上述编程语言的语法知识生成了这些答案的，这些知识是从训练它的大量数据中获得的。许多专家和观察人士认为，随着 ChatGPT 的发展，人工智能已经成为主流。ChatGPT 的真正力量将在未来几个月或几年里被看到。OpenAI 的另一个令人惊叹的在线人工智能工具是 DALL-E 2，它以卡通机器人 WALL-E（LCTT 译注：电源《机器人总动员》中的主角）和著名画家/艺术家 萨尔瓦多·达利 Salvador Dalí 的名字命名。DALL-E 2 是一个可以根据英文描述来生成绘画的人工智能系统。该工具支持丰富的图像风格，如油画、卡通、漫画、现实主义、超现实主义、壁画等。它还可以模仿著名画家的风格，如达利、毕加索、梵高等。由 DALL-E 2 生成的图像质量非常高。我用下面的描述测试了这个工具：“一个快乐的人在海滩旁看日出的立体主义画作”。图 2 是 DALL-E 2 根据我的描述生成的图像之一。立体主义是毕加索推广的一种绘画风格。问问你的任何一个画家朋友，他/她都会说这确实是一幅立体主义风格的画。令人惊讶的是软件——它也许很复杂——能够模仿像毕加索、梵高、达利这样的大师。我强烈建议你体验一下它。这种体验将非常有趣，同时也体现了人工智能的威力。但请记住，像 ChatGPT 和 DALL-E 2 这样的工具也会带来很多问题，比如版权侵犯、学生的作业抄袭等。（LCTT 译注：本文的题图就是 DALL-E 3 生成的。）介绍 scikit-learnscikit-learn 是一个非常强大的机器学习 Python 库。它是一个采用 新 BSD 许可协议 new BSD licence （LCTT 译注：即三句版 BSD 许可证） 的自由开源软件。scikit-learn 提供了回归、分类、聚类和降维等当面的算法，如 支持向量机 Support Vector Machine （SVM）、随机森林、k-means 聚类等。在下面关于 scikit-learn 的介绍中，我们将通过代码讨论支持向量机。支持向量机是机器学习中的一个重要的监督学习模型，可以用于分类和回归分析。支持向量机的发明人 Vladimir Vapnik 和 Alexey Chervonenkis。他们还一起提出了 VC 维 Vapnik–Chervonenkis dimension 概念，这是一个评估模型分类能力的理论框架。图 3 是使用支持向量机对数据进行分类的程序。第 1 行从 scikit-learn 导入 svm 模块。跟前面几篇中介绍的 python 库一样，scikit-learn 也可以通过 Anaconda Navigator 轻松安装。第 2 行定义了一个名为 X 的列表，其中包含训练数据。X 中的所有元素都是大小为 3 的列表。第 3 行定义了一个列表 y，其中包含列表 X 中数据的类别标签。在本例中，数据属于两个类别，标签只有 0 和 1 两种。但是使用该技术可以对多个类别的数据进行分类。第 4 行使用 svm 模块的 SVC() 方法生成一个支持向量分类器。第 5 行使用 svm 模块的 fit() 方法，根据给定的训练数据（本例中为数组 X 和 y）拟合 svm 分类器模型。最后，第 6 行和第 7 行基于该分类器进行预测。预测的结果也显示在图 3 中。可以看到，分类器能够正确区分我们提供的测试数据。图 4 中的代码是一个使用 SVM 进行回归的例子。第 1 行次从 scikit-learn 导入 svm 模块。第 2 行定义了一个名为 X 的列表，其中包含训练数据。注意，X 中的所有元素都是大小为 2 的列表。第 3 行定义了一个列表 y，其中包含与列表 X 中的数据相关的值。第 4 行使用 svm 模块的 SVR() 方法生成支持向量回归模型。第 5 行使用 svm 模块的 fit() 方法，根据给定的训练数据（本例中为数 X 和 y）拟合 svm 回归模型。最后，第 6 行根据该 svm 回归模型进行预测。此预测的结果显示在图 4 中。除了 SVR() 之外，还有 LinearSVR() 和 NuSVR() 两种支持向量回归模型。将第 4 行替换为 regr = svm.LinearSVR() 和 regr = svm.NuSVR()，并执行代码来查看这些支持向量回归模型的效果。现在让我们把注意力转到神经网络和 TensorFlow 上。但在下一篇讲无监督学习和聚类时，我们还会学习 scikit-learn 提供的其他方法。神经网络和 TensorFlow在上一篇中我们已经看到了 TensorFlow 的 nn 模块提供的 ReLU （ 整流线性单元 rectified linear unit ）和 Leaky ReLU 两个激活函数，下面再介绍两个其他激活函数。tf.nn.crelu() 是串联 ReLU 激活函数。tf.nn.elu() 是 指数线性单元 exponential linear unit 激活函数。我们将在后续用 TensorFlow 和 Keras 训练我们的第一个模型时用到其中一个激活函数。在开始训练模型之前，我想向你分享 TensorFlow 的提供的“神经网络实验场”工具。它通过可视化的方式帮助你理解神经网络的工作原理。你可以直观地向神经网络中添加神经元和隐藏层，然后训练该模型。你可以选择 Tanh、Sigmoid、Linear 和 ReLU 等激活函数。分类模型和回归模型都可以使用该工具进行分析。训练的效果以动画的形式显示。图 5 显示了一个示例神经网络和它的输出。你可以通过 https://playground.tensorflow.org 访问它。训练第一个模型现在，我们使用 上一篇 提到的 MNIST 手写数字数据集来训练模型，然后使用手写数字图像对其进行测试。完整的程序 digital.py 相对较大，为了便于理解，我将程序拆分成几个部分来解释，并且添加了额外的行号。import numpy as np from tensorflow import keras, expand_dims from tensorflow.keras import layers num_classes = 10 input_shape = (28, 28, 1) (x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data( ) 第 1 行到第 3 行加载必要的包和模块。第 4 行将类别的数量定义为 10，因为我们试图对 0 到 9 进行分类。第 5 行将输入维度定义为 (28,28,1)，这表明我们使用是 28 x 28 像素的灰度图像数据。第 6 行加载该数据集，并将其分为训练数据和测试数据。关于该数据集的更多信息可以参考 上一篇 的相关介绍。x_train = x_train.astype("float32") / 255 x_test = x_test.astype("float32") / 255 x_train = np.expand_dims(x_train, 3) x_test = np.expand_dims(x_test, 3) y_train = keras.utils.to_categorical(y_train, num_classes) y_test = keras.utils.to_categorical(y_test, num_classes) 第 7 行和第 8 行将图像像素值从 [0,255] 转换到 [0,1]。其中 astype() 方法用于将整数值类型转换为浮点值。第 9 行和第 10 行将数组 x_test 和 x_train 的维度从 (60000,28,28) 扩展为 (60000,28,28,1)。列表 y_train 和 y_test 包含从 0 到 9 的 10 个数字的标签。第 11 行和第 12 行将列表 y_train 和 y_test 转换为二进制类别矩阵。 try: model = keras.models.load_model(“existing_model”) except IOError: model = keras.Sequential( [ keras.Input(shape=input_shape), layers.Conv2D(32, kernel_size=(3, 3), activation=”relu”), layers.MaxPooling2D(pool_size=(2, 2)), layers.Conv2D(64, kernel_size=(3, 3), activation=”relu”), layers.MaxPooling2D(pool_size=(2, 2)), layers.Flatten( ), layers.Dropout(0.5), layers.Dense(num_classes, activation=”softmax”), ] ) batch_size = 64 epochs = 25 model.compile(loss=”categorical_crossentropy”, optimizer=”adam”, metrics=[“accuracy”]) model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs, validation_split=0.1) model.save(“existing_model”) 训练模型是一个处理器密集和高内存消耗的操作，我们可不希望每次运行程序时都要重新训练一遍模型。因此，在第 13 行和第 14 行中，我们先尝试从 existing_model 目录加载模型。第一次执行此代码时，没有模型存在，因此会引发异常。第 16 到 21 行通过定义、训练和保存模型来处理这个异常。第 16 行代码（跨越多行）定义了模型的结构。这一行的参数决定了模型的行为。我们使用的是一个序列模型，它有一系列顺序连接的层，每一层都有一个输入张量和一个输出张量。我们将在下一篇文章中讨论这些定义模型的参数。在此之前，将这个神经网络看作一个黑箱就可以了。第 17 行将批大小定义为 64，它决定每批计算的样本数量。第 18 行将 epoch 设置为 25，它决定了整个数据集将被学习算法处理的次数。第 19 行对模型的训练行为进行了配置。第 20 行根据给定的数据和参数训练模型。对这两行代码的详细解释将推迟到下一篇文章中。最后，第 21 行将训练好的模型保存到 existing_model 目录中。模型会以多个 .pb 文件的形式保存在该目录中。注意，第 16 到 21 行位于 except 块中。print(model.summary( )) score = model.evaluate(x_test, y_test, verbose=0) print(“Test loss:”, score[0]) print(“Test accuracy:”, score[1]) 第 22 行打印我们训练的模型的摘要信息（见图 6）。回想一下，在加载数据集时将其分为了训练数据和测试数据。第 23 行使用测试数据来测试我们训练的模型的准确性。第 24 行和第 25 行打印测试的详细信息（见图 8）。img = keras.utils.load_img("sample1.png").resize((28, 28)).convert('L') img = keras.utils.img_to_array(img) img = img.reshape((1, 28, 28, 1)) img = img.astype('float32')/255 score = model.predict(img) print(score) print("Number is", np.argmax(score)) print("Accuracy", np.max(score) * 100.0) 现在，是时候用实际数据来测试我们训练的模型了。我在纸上写了几个数字，并扫描了它们。图 7 是我用来测试模型的一个图像。第 26 行加载图像，然后将其大小调整为 28 x 28 像素，最后将其转换为灰度图像。第 27 到 29 行对图像进行必要的预处理，以便将它输入到我们训练好的模型中。第 30 行预测图像所属的类别。第 31 到 33 行打印该预测的详细信息。图 8 显示了程序 digital.py 的这部分输出。从图中可以看出，虽然图像被正确识别为 7，但置信度只有 23.77%。进一步，从图 8 中可以看到它被识别为 1 的置信度为 12.86%，被识别为 8 或 9 的置信度约为 11%。此外，该模型甚至在某些情况下会是分类错误。虽然我找不到导致性能低于标准的准确原因，但我认为相对较低的训练图像分辨率以及测试图像的质量可能是主要的影响因素。这虽然不是最好的模型，但我们现在有了第一个基于人工智能和机器学习原理的训练模型。希望在本系列的后续文章中，我们能构建出可以处理更困难任务的模型。在本文介绍了 scikit-learn，在下一篇文章中我们还会继续用到它。然后介绍了一些加深对神经网络的理解的知识和工具。我们还使用 Keras 训练了第一个模型，并用这个模型进行预测。下一篇文章将继续探索神经网络和模型训练。我们还将了解 PyTorch，这是一个基于 Torch 库的机器学习框架。PyTorch 可以用于开发 计算机视觉 computer vision （CV） 和 自然语言处理 natural language processing （NLP） 相关的应用程序。致谢：感谢我的学生 Sreyas S. 在撰写本文过程中提出的创造性建议。（题图：DA/c8e10cac-a5a5-4d53-b5eb-db06f448e60e）via: https://www.opensourceforu.com/2023/02/ai-an-introduction-to-scikit-learn-and-our-first-trained-model/作者：Deepu Benson 选题：lujun9972 译者：toknow-gh 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
以下是使用 WSL 关闭在 Windows 内运行的 Linux 系统的不同方法。你使用 WSL 在 Windows 内运行 Linux 吗？你想知道如何关闭在 WSL 中运行的 Linux 发行版吗？你当然可以在 WSL 中运行的 Linux 系统中 执行 shutdown 命令：sudo shutdown now 你还可以使用 wsl 命令关闭 Linux 系统。如果你有多个发行版在 WSL 中运行，这是一种极好的方法。在 WSL 中使用 Windows 终端关闭 Linux 系统在这个方法中，我假设通常的 shutdown 命令在 WSL Linux 系统中不起作用。首先，在 Windows 中打开一个终端。在这里，我使用的是 Windows 11，并在 WSL 2 下安装了 Ubuntu。? 你可以在标准的 Windows 终端上使用 wsl 命令。在运行的 Linux 发行版中也可以访问该命令。这里，命令的名称是 wsl.exe。现在，你需要列出已安装的发行版及其状态。为此，请输入wsl --list --verbose 或 wsl -l -v 在这里，你可以看到，我已经安装了一个 WSL Ubuntu，它目前正在运行。关闭所有正在运行的 Linux 发行版有时，你可能想一次性停止正在运行的 WSL 实例。在 Powershell 或 Windows 终端中，使用以下命令：wsl --shutdown 这将关闭所有会话。此外，你还可以在任何正在运行的 WSL Linux 发行版终端中执行相同的功能。在发行版中时，你只需要使用 wsl.exe 而不是 wsl。wsl.exe --shutdown 运行此命令后，所有正在运行的 WSL 发行版都将终止。WSL 2 轻量级虚拟机也被终止。因此，如果你想重新启动 WSL 2 虚拟机环境，它将很有用。终止特定的 Linux 发行版要终止特定正在运行的 WSL 发行版，请打开单独的 Windows 终端并运行：wsl --terminate <发行版名称> 此处，发行版名称是你使用 wsl -l -v ⁣ 命令列出所有已安装的 WSL 发行版时获得的名称。wsl --terminate Ubuntu 执行后，指定的 Linux 发行版将被终止。如果你在另一个发行版中，请使用以下命令列出系统上安装的所有 WSL 发行版：wsl.exe -l -v 现在，使用以下命令终止所需的发行版：wsl.exe --terminate <发行版名称> 总结有些人直接关闭正在运行的 Linux 应用，但我认为这不太优雅。另外，就像 Linux 终端一样，你可以使用：logout 命令，用于关闭该发行版。exit 命令用于退出运行 Linux 发行版的终端。或者，按 CTRL+D 执行与 exit 命令相同的操作。但关闭 Linux 系统的 WSL 方式还有一个额外的优势，即可以针对多个 Linux 系统执行此操作。我希望它对你有帮助。（题图：DA/615fd564-a02c-4340-9c8f-ebabcc7c0e0c）via: https://itsfoss.com/shut-down-wsl-distros/作者：Sreenath 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
在 Linux 中，你可以根据自己的需要创建高级网络设置，如 网络绑定 Network Bonding 或 网卡聚合 NIC teaming 、VLAN 标记和桥接。这些高级功能可以提高网络连接的效率和可靠性。你可以在以太网、绑定、聚合或桥接设备等其他接口上创建 VLAN 接口。在本文中，我们将学习如何在 RHEL 系统中通过网络绑定配置 VLAN 标记，它允许来自不同网络的流量共享共同的物理链接。通过绑定对 VLAN 进行标记的先决条件网络聚合需要在网络交换机端口上启用 LACP（802.3ad），以聚合链路。网络聚合需要将网络端口配置为中继端口，这样可以在同一端口上添加多个 VLAN。此外，还要从它们那里获取 VLAN ID，以便在操作系统层面进行配置。Linux 系统应该有两个接口。如果是物理服务器，我们建议在板载接口和 PCI 接口之间配置绑定，以避免主机端的网卡出现单点故障。绑定内核模块使用 lsmod 命令检查 Linux 系统是否已加载绑定模块。lsmod | grep -i bonding bonding 12451 0 默认情况下已加载。否则，请使用 modprobe 命令加载它。modprobe bonding 1) LACP 绑定配置我们将配置基于 LACP（Mode 4 – 802.3ad）的链路聚合绑定，通过组合名为 em1 和 p7p1 的两个接口，为绑定接口提供更大的带宽。1a) 创建 Bond 接口在目录 /etc/sysconfig/network-scripts/ 下创建绑定接口文件 ifcfg-bond0。vi /etc/sysconfig/network-scripts/ifcfg-bond0 TYPE=Bond DEVICE=bond0 NAME=bond0 BONDING_MASTER=yes BOOTPROTO=none ONBOOT=yes BONDING_OPTS="mode=4 miimon=100 lacp_rate=1" NM_CONTROLLED=no 1b) 配置第一个从接口配置你想要进行绑定的第一个从属接口 em1。请根据你的环境使用正确的接口名称。vi /etc/sysconfig/network-scripts/ifcfg-em1 TYPE=Ethernet BOOTPROTO=none DEVICE=em1 ONBOOT=yes MASTER=bond0 SLAVE=yes 1c) 配置第二个从接口配置你想要进行绑定的第二个从属接口 p7p1。 请根据你的环境使用正确的接口名称。vi /etc/sysconfig/network-scripts/ifcfg-p7p1 TYPE=Ethernet BOOTPROTO=none DEVICE=p7p1 ONBOOT=yes MASTER=bond0 SLAVE=yes 重启网络服务重启网络服务以启用绑定接口或使用 ifup 命令启动它们。systemctl restart network 2) 通过绑定接口进行 VLAN 标记LACP 绑定配置已完成，所有接口现已启动并运行。让我们按照以下步骤配置绑定接口上的 VLAN 标记。正如先决条件中所讨论的，以下是映射到相应以太网卡端口（em1 和 p7p1）和网络交换机端口的 VLAN。VLAN ID (221), VLAN N/W = 192.168.10.0/24VLAN ID (331), VLAN N/W = 192.168.20.0/242a) 将 VLAN 221 配置到 Bond0为 VLAN id 221 创建标记接口文件 /etc/sysconfig/network-scripts/ifcfg-bond0.221 并添加以下内容。vi /etc/sysconfig/network-scripts/ifcfg-bond0.221 DEVICE=bond0.221 BOOTPROTO=none ONBOOT=yes IPADDR=192.168.10.100 NETMASK=255.255.255.0 GATEWAY=192.168.10.1 VLAN=yes NM_CONTROLLED=no 2b) 将 VLAN 331 配置到 Bond0为 VLAN id 331 创建标记接口文件 /etc/sysconfig/network-scripts/ifcfg-bond0.331 并添加以下内容。vi /etc/sysconfig/network-scripts/ifcfg-bond0.331 DEVICE=bond0.331 BOOTPROTO=none ONBOOT=yes IPADDR=192.168.20.100 NETMASK=255.255.255.0 GATEWAY=192.168.20.1 VLAN=yes NM_CONTROLLED=no 重启网络服务重启网络服务以启用绑定接口或使用 ifup 命令启动它们。systemctl restart network 验证 VLAN 标记配置最后使用 ip 命令 验证 VLAN 标记接口是否已配置并启动和运行。是的，我可以看到 bondo.221@bond0 和 bon0.331@bond0 有两个不同的 IP，并且能够通过 ssh 访问系统，没有任何问题。因此，VLAN 标记按预期工作。结论恭喜，你已经了解了如何在 RHEL 系统上通过 LACP 绑定配置 VLAN 标记，该系统监听两个 VLAN。VLAN 标记不限于两个 VLAN，支持多个 VLAN，你可以根据该 VLAN 的网络配置添加 VLAN 标记。（题图：DA/2854516d-4d19-4008-a421-05f9a2a78368）via: https://www.2daygeek.com/configure-vlan-tagging-over-network-bonding-rhel/作者：Jayabal Thiyagarajan 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
使用 VLC 媒体播放器播放和管理字幕的新手指南。我是一个超级动漫迷，如果你想观看最新的剧集，那么你只能观看日语音频，因此字幕对于非日语观众来说是必不可少的。值得庆幸的是，我最喜欢的视频播放器 VLC 很好地支持字幕。难怪它是有史以来 最好的视频播放器 之一。VLC 实际上可以做的不仅仅是播放提供的字幕。在本指南中，我将引导你完成以下内容：如何使用可用的字幕（如果有的话）如何使用下载的字幕如何自动下载字幕（使用 vlsub 扩展）如何将字幕与视频同步VLC 支持哪些字幕格式那么让我们从第一个开始。如何在 VLC 中启用字幕有些视频附带字幕文件。如果字幕与视频文件位于同一文件夹中，你可以轻松启用字幕。虽然启用字幕的方法有多种，但我将向你展示两种有效的方法。按 V 键（最简单的方法）如果当前播放的视频有一个或多个字幕，那么你可以按 V 键，它将在可用选项之间更改字幕。正如你所看到的，当我按下 V 时，它会在多个字幕之间漫游，甚至可以选择完全禁用字幕。使用顶部菜单栏或右键单击上下文菜单虽然按 V 键是启用字幕的最简单方法，但如果你有多个字幕文件（可能有多种语言）并且必须选择其中之一，那么按 V 键的效果就不是最好了。假设你要查找的字幕位于最后一个位置，那么你必须按 V 键几次，如果你错过了，请再次重复该过程。因此，在这种情况下，从顶部菜单中选择字幕轨道是一种简单方便的方法。要使用此方法，你必须遵循两个简单的步骤：单击顶部菜单栏中的 “ 字幕 Subtitle ” 菜单选择 “ 子轨道 Sub Track ”，然后选择所需的字幕轨道你还可以通过右键单击正在播放的视频，并选择字幕选项来完成此操作。如何在 VLC 中使用下载的字幕如果你从网上下载了字幕，但不知道如何在 VLC 中使用它们，那么本节将解决该问题。要使用下载的字幕，你必须将其导入 VLC。并且可以通过遵循给定的简单步骤轻松完成：首先，单击顶部菜单栏中的 “字幕”选择第一个 “ 添加字幕文件 Add Subtitle File ” 选项，它将打开文件管理器从这里找到字幕文件所在的位置并选择它完成后，可以通过顶部菜单栏中的字幕菜单访问添加的字幕：? 如果你要保存视频以供将来使用，我建议将字幕文件复制到与视频文件本身相同的文件夹中。更好的方法是将文件重命名为与视频文件相同的名称。因此，如果视频文件是 my-xyz.mp4，则字幕文件应该是 my-xyz.srt。这样，字幕要么自动播放，要么在你按 v 键时被识别。如何在 VLC 中自动下载字幕（适用于 Linux 用户）你是否知道 VLC 有一个名为 VLsub 的插件，可用于从网络下载字幕并直接在 VLC 中访问它们？如果你是 Linux 用户，请按照给定的说明将其添加到 VLC 中。首先，使用 wget 命令 下载 zip 文件：wget https://github.com/exebetche/vlsub/archive/master.zip 接下来，如下所示 使用 unzip 命令解压文件：unzip master.zip 之后，你需要 创建一个新目录：mkdir -p ~/.local/share/vlc/lua/extensions 最后，使用 mv 命令 将文件移动到创建的目录，如下所示：mv ~/vlsub-master/vlsub.lua ~/.local/share/vlc/lua/extensions 现在，打开VLC播放器，在 “ 视图 View ” 菜单下，你将找到 “VLsub”：要使用 VLsub 下载字幕，首先，输入电影名称和年份以获得更好的结果，然后点击“ 按名称搜索 Search by name ”按钮，从结果中选择字幕文件，然后单击“ 下载选择 Download selection ”按钮，如图所示 :就是这样！要了解有关如何使用 VLsub 扩展的更多信息，请参阅我们有关该主题的 详细指南。如何在 VLC 中将字幕与电影同步有时，下载的字幕可能会比电影中发生的事情稍微落后或提前，这可能会令人沮丧！不用担心！ VLC也有解决这个问题的方法！在 VLC 中，你可以通过按 G 和 H 键前进或后退字幕。G 键将使字幕快进 50 毫秒H 键将使字幕后退 50 毫秒虽然 50 毫秒听起来太短，但你会在 2-3 次按键内注意到显着差异。如果你在实际场景中跑得太超前或落后，也可以按住它们。还感到困惑吗？ 你可以参考我们的 如何在 VLC 中同步字幕的详细指南。VLC 支持哪些字幕格式？如果你想从互联网上下载字幕，那么你必须了解 VLC 支持的字幕格式。以下是 VLC 支持的字幕格式列表：*.idx（VOBSub）*.cvd（Chaoji VCD）*.usf（通用字幕）*.ttxt（MPEG-4 定时文本）*.srt（SubRip）*.ssa（Sub Station Alpha）*.smi（SAMI）*.aqt（AQTitle）*.txt（ML2/VPlayer）*.rt（RealText/Smil）*.psb（PowerDivX）*.pjs（Phoenix Subtitle）*.dks（DKS）*.mpl（ML2）*.jss（JACOSub）*.svcd（Super Video CD）*.txt（ML2/VPlayer）但最流行的微妙类型是 *.srt，并且通常在你下载视频文件时默认提供。VLC 的功能远不止播放视频你知道可以使用 VLC 下载 YouTube 视频吗？ 嗯，它可以做的远不止这些。为此，我们制作了关于 你可以使用 VLC 播放器做的很酷的事情 的详细指南。以下是如何充分利用 VLC 的方法：让 VLC 播放器在 Linux 中发挥更大作用的 5 个技巧我希望本指南对你有所帮助。（题图：DA/39a917f2-a1b3-4167-8393-1af0859105b0）via: https://itsfoss.com/vlc-use-subtitles/作者：Sagar Sharma 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
Obsidian 知识库工具的真正威力在于链接。学习使用它。Obsidian 的最大卖点之一是其强大的文档链接和可视化。Obsidian 提供了多种链接文档和图像的方法。我们将逐一介绍。你将在 Obsidian 中看到三种内部链接方法：拖放方式（简单但有限）使用 Markdown 链接使用维基链接（广泛且强大）我还将分享一些有关使用图表和反向链接的技巧。让我们来看看它。✋ 非自由和开源软件警告！ Obsidian 不是开源软件，我们知道这一事实。然而，它是一种在编码人员（包括开源开发人员）中非常流行的工具。这就是我们介绍它的原因。方法 1：通过拖放链接是的，这是最简单的链接。转到要在其中创建链接的文档。现在，在左侧边栏上，展开该特定文件夹，其中包含目标注释。要创建链接，只需将此目标文件拖放到你希望链接显示的位置即可。你可以稍后更改链接文本。方法 2：使用 Markdown 链接由于 Obsidian 使用 Markdown 作为其核心，因此可以通过输入传统的 Markdown 命令进行链接。比方说，你必须在 “Markdown Advanced” 页面中创建一个指向 “Markdown Checklist” 页面的链接。首先，你需要记下要链接到的文件的位置。然后，只需添加这一行：[链接文本]（文件的相对路径） 或者，如果你有要链接的文件，并且想要提供系统中的绝对路径，请使用：[链接文本](file://绝对路径) ? 如果你 使用 Markdown 链接，请确保文件和文件夹的名称中没有空格，因为这在某些情况下可能会引起一些麻烦。方法 3：使用紧凑型维基链接来链接页面Obsidian 支持使用 维基链接 Wikilink 来链接页面的直观方式。它们是紧凑的链接并且是交互式链接。默认情况下，此功能处于打开状态。如果你想知道，是的，它与维基百科有关。他们用它来内部链接他们的维基页面。添加内部注释的链接要创建链接，只需输入 [[。这将启动一个交互式对话框，你可以在其中搜索要链接的文档。? 你可以使用 要显示的文本使自定义文本显示在维基链接上。例如 这是 Hello 文件的链接添加图像文件此外，你可以使用此链接方法添加其他文件，例如图像，但在使用 [[ 搜索之前需要添加 ! 符号。请看下图以了解其实际效果。添加内部标题链接有一种方法可以在同一页面的各个标题之间创建内部链接。为此，首先输入 [[，然后使用 Markdown 标题语法和要链接的特定标题的名称。例如，如果你打算链接到文档中的第六个标题（2 级标题），请使用：[[##Paragraph Six 这将显示在交互式选择中。? 你可以将鼠标悬停在链接上时按 CTRL 键来进行预览。添加指向文本块的链接Obsidian 允许你创建指向文档中特定文本块的链接。为此，首先，转到要添加链接的块的最末尾。现在，使用 ^ 符号向该块添加唯一标识符。现在，你可以通过输入 [[^ 来添加到此部分的链接。这将自动提示你可用的块。选择一项并按回车键。维基链接的问题有时，如果你想要纯 Markdown 文档，并且专注于多个 Markdown 编辑器之间的互操作性，那么维基链接功能可能会产生问题。由于这些在 Obsidian 内部工作，因此链接在其他编辑器上显示为损坏。在这种情况下，你可以关闭维基链接。一切都完美无缺，只是链接现在将以 Markdown 格式显示。为此，首先选择左下角的设置按钮。现在，从 “ 文件和链接 Files and Links ” 选项卡关闭维基链接功能。组织附件文件的提示对于那些在 Obsidian 中附加许多文件的人，建议在每本书下为这些附件创建一个单独的文件夹。现在，打开 “ 设置 Settings > 文件和链接 Files and Links ”。在这里，首先，你需要确保链接路径是相对于文件位置的。然后，将新附件的默认位置设置为 “ 当前文件夹下的子文件夹 Subfolder under current folder ”。现在，在下一个字段中指定 “ 附件 Attachments ”，即 “ 子文件夹名称 Subfolder name ”。就是这样。从现在开始，当你通过复制和粘贴放置任何附件时，它们将自动放置在该笔记文件夹内的“附件”文件夹中。新链接将在任何 Markdown 编辑器之间完美地互操作，因为路径现在是相对于文件位置的。? 即使此维基链接功能已关闭，你仍然可以使用 [[ 键以交互方式搜索和添加链接。变化是，现在链接不再是紧凑的，而是长 Markdown 链接。此外，你还可以打开 “ 自动更新内部链接 Automatically Update Internal Links ” 按钮，以确保在重命名文件时自动更新链接。使用图表和反向链接创建完链接后，就可以通过链接查看笔记之间的其他笔记之间的关系。单击侧面的图表视图按钮即可进入图表预览。正如你所看到的，你将在一个整洁的图表上获得该注释的链接。如果你按空白选项卡上的图表视图，你将获得所有笔记及其关系。此外，每个笔记都有一 “传出链接” 和 “传入链接” 选项卡，你可以在其中跟踪相关链接。总结正如你所看到的，虽然在 Obsidian 中创建指向其他页面的内部链接很简单，但通过维基链接，你可以创建更加个性化和定制的知识库。对于那些不喜欢 Obsidian 闭源性质的人来说，Logseq 是一个不错的选择。（题图：DA/57173f4d-5548-471f-8d70-a48e3b5e964a）via: https://itsfoss.com/obsidian-create-links/作者：Sreenath 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
使用 GNOME 的 Nautilus 文件搜索，通过这些方便的提示改善您的文件搜索体验，成为一名专业的搜索者。GNOME 的 Nautilus 文件管理器功能丰富。不信？看看这篇文章，你就会知道如何将 Nautilus 的全部功能 发挥到极致。文件搜索是 Nautilus 被忽视的功能之一。没有多少 Linux 用户充分发挥了它的潜力。因此，我编写了本教程，与大家分享一些使用 Nautilus 文件管理器中文件搜索选项的技巧。我知道经验丰富的 Linux 用户可以使用终端中的 find 命令 实现相同的目的，但许多桌面用户更喜欢使用 GUI。让我们从最简单的搜索选项开始。按名称搜索文件打开 Nautilus 并单击顶部栏上的放大镜。这将打开一个搜索栏，你可以在其中输入查询字符串。当你输入时，搜索结果会不断完善，并在输入完整文件名时进行匹配。? 搜索在当前目录及其子目录中执行。可以启用 隐藏文件视图，将隐藏文件包含在搜索结果中。根据时间搜索文件使用 Nautilus，你可以根据文件的创建、修改或上次访问的时间过滤搜索。为此，请单击搜索按钮并开始输入。当你开始输入时，你会注意到搜索按钮附近有一个下拉菜单。点击它。这将为你提供一个菜单，其中包含用于过滤搜索的选项。单击下拉菜单上的 “ 选择日期 Select Dates ” 按钮。另外，选择选项 “ 文件名 File Name ” 以按文件名匹配。这将为你提供一个扩展菜单，你可以在其中选择文件创建、修改或上次访问的日期。在这里，如果你想设置自定义日期，请单击日历图标，如下图所示：现在，你将看到一个小日历，并可以相应地选择日期。从列表中设置你选择的日期后，你可以看到搜索栏上应用的条件，并向你显示基于该条件的文件。根据文件类型搜索文件你还可以根据文件类型过滤搜索。假设你正在寻找 PDF 文件。与上一步一样，单击搜索图标并开始输入文件名。现在，从下拉菜单中，单击 “ 任何 Anything ” 选项并选择 “ 文件名 File Name ”。从展开的视图中选择要搜索的文件类型。在这里，我选择了 “PDF/Postscript”。选择所需的文件类型后，你可以在搜索栏上看到应用的条件。你还将看到相应的结果。在搜索选项中没有找到所需的文件类型？向下滚动到底部并单击 “ 其他类型 other types ”。这将为你提供更多文件类型。搜索文件内容，而不是名称默认情况下，根据文件名执行文件搜索。如果你想知道是否有包含特定单词的文件，Nautilus 也允许你这样做。首先，单击搜索图标并开始输入。现在，与前面的部分一样，转到下拉菜单。在下拉菜单中，不要选择 “ 文件名 File Name ”，而是选择 “ 全文 Full Text ”。现在，你可以搜索特定字符串并根据特定日期或文件类型进行搜索过滤。过滤的方法与前面提到的相同。在这里，我使用了字符串 “text to be”，你可以看到列出了几个具有该特定字符串的文件。另外，你可以看到，该部分也突出显示。仅搜索文件或仅搜索文件夹默认情况下，Nautilus 会搜索文件和文件夹。你可以将搜索细化为文件或文件夹。为此，请在下拉菜单中选择 “ 文件名 File Name ”，然后从类型列表中选择 “ 文件 Files ” 或 “ 文件夹 Folders ”，如下所示。这将根据你的选择过滤结果。应用多个过滤器你可以将日期过滤器和类型过滤器组合在一起以获得更精确的搜索。为此，请从各自的下拉列表中选择每个条件。你可以在下面的截图中看到，我已经搜索了包含字符串 “to be search” 的文件。我应用的标准是 1 天内创建的 PDF 文件。更多 Nautilus 提示和调整Nautilus 足以满足大多数搜索场景。如果你需要更多，还有专用的 GUI 工具，可让你执行桌面范围的自定义搜索。ANGRYsearch - 用于 Linux 的快速搜索图形用户界面工具想要更多这样的 Nautilus 技巧吗？ 以 root 身份打开文件 怎么样？在 Nautilus 文件管理器中以管理员身份打开文件和文件夹或者将终端的功能与文件管理器结合起来？在 Linux 中混合搭配终端与 Nautilus 文件管理器这里还有更多此类提示。请自行查看。在 Linux 中调整 Nautilus 文件管理器的 13 种方法我希望你喜欢这些技巧，它们有助于更好地改善你的桌面 Linux 体验。你还知道其他这样酷的技巧吗？ 请在评论中分享。（题图：DA/77ae519f-e942-42b0-9808-4af943b168cb）via: https://itsfoss.com/nautilus-file-search/作者：Sreenath 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
在本文中我们将继续学习概率论的知识。在本系列的 上一篇文章中，我们学习了使用 Anaconda，加强了概率论的知识。在本文中我们将继续学习概率论的知识，学习使用 seaborn 和 Pandas 进行数据可视化，并进一步介绍 TensorFlow 和 Keras 的使用。让我们从增长人工智能和机器学习的理论知识开始。众所周知人工智能、机器学习、数据科学、深度学习等是当今计算机科学的热门话题。然而，计算机科学还其他热门的话题，比如 区块链 blockchain 、 物联网 Internet of Things （IoT）、 量子计算 quantum computing 等。那么，人工智能领域的发展是否会对这些技术产生积极的影响呢？首先，让我们讨论一下区块链。根据维基百科的定义，“区块链是一种分布式账本，它由不断增长的记录（称为 区块 block ）组成，这些记录使用加密技术安全地连接在一起。”乍一看，人工智能和区块链似乎是两个高速发展的独立技术。但令人惊讶的是，事实并非如此。区块链相关的行话是 完整性 integrity ，人工智能相关的行话是数据。我们将大量数据交给人工智能程序去处理。虽然这些应用程序产生了惊人的结果，但我们如何信任它们呢？这就提出了对可解释的人工智能的需求。它可以提供一定的保证，以便最终用户可以信任人工智能程序提供的结果。许多专家认为，区块链技术可以用来提高人工智能软件做出的决策的可信度。另一方面， 智能合约 smart contract （区块链技术的一部分）可以从人工智能的验证中受益。从本质上讲，智能合约和人工智能通常都是做决策。因此，人工智能的进步将对区块链技术产生积极影响，反之亦然。下面让我们讨论一下人工智能和物联网之间的影响。早期的物联网设备通常没有强大的处理能力或备用电池。这使得需要大量处理能力的机器学习的软件无法部署在物联网设备上。当时，大多数物联网设备中只部署了基于规则的人工智能软件。基于规则的人工智能的优势在于它很简单，需要相对较少的处理能力。如今的物联网设备具备更强大的处理能力，可以运行更强大的机器学习软件。特斯拉开发的高级驾驶辅助系统 特斯拉自动驾驶仪 Tesla Autopilo 是物联网与人工智能融合的典范。人工智能和物联网对彼此的发展产生了积极影响。最后，让我们讨论人工智能和量子计算是如何相互影响的。尽管量子计算仍处于起步阶段，但 量子机器学习 quantum machine learning （QML）是其中非常重要的课题。量子机器学习基于两个概念：量子数据和量子-经典混合模型。量子数据是由量子计算机产生的数据。 量子神经网络 quantum neural network （QNN）用于模拟量子计算模型。TensorFlow Quantum 是一个用于量子-经典混合机器学习的强大工具。这类工具的存在表明，在不久的将来将会有越来越多的基于量子计算的人工智能解决方案。seaborn 入门seaborn 是一个基于 Matplotlib 的数据可视化 Python 库。用它能够绘制美观且信息丰富的统计图形。通过 Anaconda Navigator 可以轻松安装 seaborn。我用 ESPNcricinfo 网站上 T20 国际板球赛的击球记录，创建了一个名为 T20.csv 的 CSV（ 逗号分隔值 comma-separated value ）文件，其中包含以下 15 列：球员姓名、职业生涯跨度、比赛场次、局数、未出局次数、总得分、最高得分、平均得分、面对球数、击球率、百分次数、五十分次数、零分次数、四分次数和六分次数。图 1 是使用 Pandas 库读取这个 CSV 文件的程序代码。我们已经在前面介绍过 Pandas 了。下面逐行解释程序代码的作用。第 1 行和第 2 行导入 Pandas 和 seaborn 包。第 3 行从 JupyterLab 的工作目录中读取文件 T20.csv。第 4 行打印元数据和第一行数据。图 1 显示了这行数据，它显示了 T20 国际板球赛中得分最高的 Virat Kohli 的击球记录。第 5 行将元数据和 T20.csv 中的前五行数据保存到 Best5.csv 中。在执行该行代码时会在 JupyterLab 的工作目录中创建这个文件。第 6 行根据列百分次数按升序对 CSV 文件进行排序，并将前 10 名世纪得分手的详细信息存储到 Highest100.csv 中。该文件也将存储在 JupyterLab 的工作目录中。最后，第7行代码提取了第 5 列（总得分）和第 7 列（平均得分）的数据信息，并生成散点图。图 2 显示了程序在执行时生成的散点图。在程序末尾添加如下代码行并再次运行。sns.kdeplot(data=df.iloc[:, [5, 7]].head(50), x=’Ave’, y=’Runs’) 这行代码调用 kdeplot() 函数绘制第 5 列和第 7 列数据的 核密度估计 Kernel Distribution Estimation （KDE）图。KDE 图可以描述连续或非参数数据变量的概率密度函数。这个定义可能无法让您了解函数 kdeploy() 将要执行的实际操作。图 3 是在单个图像上绘制的 KDE 图和散点图。从图中我们可以看到，散点图绘制的数据点被 KDE 图分组成簇。seaborn 还提供了许多其他绘图功能。在图 1 中程序的第 7 行分别替换为下面的的代码行（一次一行），并再次执行该程序，你会看到不同风格的绘图显示。探索 seaborn 提供的其他绘图功能，并选择最适合你需求的功能。sns.histplot(data=df.iloc[:, [5, 7]].head(50), x=’Ave’, y=’Runs’) sns.rugplot(data=df.iloc[:, [5, 7]].head(50), x=’Ave’, y=’Runs’) 更多概率论在本系列之前的一篇文章中，我们看到可以用正态分布来对现实场景进行建模。但正态分布只是众多重要概率分布中的一种。图 4 中的程序绘制了三种概率分布。下面我来解释这个程序。第 1 行导入 NumPy 的 random 模块。第 2 行和第 3 行导入用于绘图的 Matplotlib 和 seaborn。第 5 行生成带有参数 n（试验次数）和 p（成功概率）的 二项分布 binomial distribution 数据。二项分布是一种离散概率分布，它给出了在一系列 n 次独立实验中成功的数量。第三个参数 size 决定了输出的形状。第 6 行绘制生成的数据的直方图。由于参数 kde=True，它还会绘制 KDE 图。第三个参数 color='r' 表示绘图时使用红色。第 7 行生成一个泊松分布。泊松分布是一种离散概率分布，它给出了二项分布的极限。参数 lam 表示在固定时间间隔内发生预期事件的次数。这里的参数 size 也决定了输出的形状。第 8 行将生成的数据绘制为绿色的直方图。第 9 行生成大小为 1000 的指数分布。第 10 行将生成的数据绘制为蓝色的直方图。最后，第 11 绘制三个概率分布的所有图像（见图 5）。NumPy 的 random 模块提供了大量的其他概率分布，如 Dirichlet 分布、Gamma 分布、几何分布、拉普拉斯分布等。学习和熟悉它们将是非常值得的。现在，让我们学习线性回归。使用线性回归分析可以根据一个变量来预测一个变量的值。线性回归的一个重要应用是数据拟合。线性回归非常重要，因为它很简单。机器学习中的监督学习范式实际上就是回归建模。因此，线性回归可以被认为是一种重要的机器学习策略。这种学习范式通常被统计学家称为统计学习。线性回归是机器学习中的重要操作。NumPy 和 SciPy 都提供了线性回归的函数。下面我们展示使用 NumPy 和 SciPy 进行线性回归的示例。图 6 是使用 NumPy 进行线性回归的程序。第 1 行和第 2 行导入 NumPy 和 Matplotlib。第 4 行和第 5 行初始化变量 a和 b。第 6 行使用函数 linspace() 在 0 和 1 之间等间隔地生成 100 个数字。第 7 行使用变量 a、b 和数组 x 生成数组 y 中的值。函数 randn() 返回标准正态分布的数据。第 8 行将数组 x 和 y 中的值绘制成散点图（见图 7），图中的 100 个数据点用红色标记。第 9 行使用函数 polyfit() 执行称为 最小二乘多项式拟合 least squares polynomial fit 的线性回归技术。函数 polyfit() 的输入参数包括数组 x 和 y，以及第三个表示拟合多项式的阶数的参数，在本例中为 1，表示拟合一条直线。该函数的返回值是多项式的系数，代码中将其存储在数组 p 中。第 10 行使用函数 polyval() 对多项式求值，并将这些值存储在数组y_l中。第 11 行用蓝色绘制拟合得到的直线（见图 7）。最后，第 12 行显示所有的图像。可以用这条回归直线预测可能的 (x, y) 数据对。图 8 是使用 SciPy 进行线性回归的程序代码。下面我解释一下这个程序的工作原理。第 1 行和第 2 行导入库 NumPy 和 Matplotlib。第 3 行从库 SciPy 导入 stats 模块。第 4 到 8 行与前面的程序执行类似的任务。第 9 行使用 SciPy 的 stats 模块的 linregression() 函数计算两组测量值的线性最小二乘回归——在本例中是数组 x 和 y 中的值。该函数返回值中的 m 和 c 分别表示回归直线的 斜率 slope 和 截距 intercept 。第 10 行使用斜率和截距的值生成回归线。第 11 行用绿色绘制回归线。最后，第 12 行显示所有的图像（见图 9），其中数据点以黄色显示，回归线以绿色显示。在本系列的前面几篇文章中，我们学习了概率和统计学的一些概念。尽管还不够全面的，但我认为这已经打下了一个良好的基础，现在是时候将注意力转移到其他同样重要的问题上了。Keras 简介Keras 一般与 TensorFlow 一起使用。因此，我们先从使用 TensorFlow 开始。图 10 所示的程序虽然只包含四行代码，但确实构建了在本系列中的第一个神经网络。下面我来介绍它的工作原理。第 1 行导入库 TensorFlow。第 2 行创建了一个名为 x 的张量。第 3 行和第 4 行分别在张量 x 上应用 ReLU（ 整流线性单元 Rectified Linear Unit ）和 Leaky ReLU 激活函数。在神经网络中，激活函数定义了节点的输出由输入计算出的规则。ReLU 激活函数是定义为 Relu(x) = max(0,x)。第 3 行代码的输出如图 10 所示。可以观察到，在应用 ReLU 激活函数后，张量 x 中的负值被替换为零。Leaky ReLU 是 ReLU 激活函数的改进版本。从图 10 中的第 4 行代码的输出可以看出 Leaky ReLU 激活函数保留了全量的正值和 20% 的负值。在后面我们将会继续讨论 Keras，同时学习更多神经网络和激活函数的知识。下面我们开始使用 Keras。Keras 的安装也可以通过 Anaconda Navigator 轻松完成。图 11 所示的程序导入了我们的第一个数据集并显示了其中的一个数据样本。在下一篇文章中，我们将使用这个数据集来训练和测试模型，从而开启我们开发人工智能和机器学习程序的下一个阶段。下面介绍这个程序的工作原理。第 1 行导入 Keras。第 2 行从 Keras 导入手写数字数据集 MNIST。它包含 6 万个训练样本和 1 万个测试样本。第 3 行导入 Matplotlib。第 5 行加载 MNIST 数据集。第 6 到 9 行打印训练集和测试集的维数和维度。图 12 显示了这些代码行的输出。可以看出，训练集和测试集都是三维的，所有数据样本的分辨率都是 28 × 28。第 10 行加载了第 1234 个训练图像。第 11 行和第 12 行显示这个图像。从图 12 可以看到它是数字 3 的手写图像。本文中我们开始涉及到神经网络，并通过 Keras 接触到了第一个数据集。在下一篇文章中，我们将继续讲解神经网络和 Keras，并通过使用该数据集训练自己的模型。我们还会遇到 scikit-learn, 它是另一个强大的机器学习 Python 库 。（题图：DA/2f8f2e0c-c9a7-4a55-8a03-3b5105721013）via: https://www.opensourceforu.com/2023/01/ai-introduction-to-keras-and-our-first-data-set/作者：Deepu Benson 选题：lujun9972 译者：toknow-gh 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
没错，即使是 GNOME 登录屏幕也可以自定义。这里有一个方便的实用工具，可以让事情变得更简单。从停靠区到 GRUB 屏幕，GNOME 都可以根据你的喜好进行定制。登录界面也在此列，因为一款名为 “ GDM 设置 GDM Settings ”的新工具可让你更改 GNOME 登录界面的外观并调整其功能。你可以更改壁纸、主题、图标、时间格式、顶部面板项目等。你还可以在登录界面启用轻击功能（我喜欢这个）。在本教程中，你将了解安装此工具的步骤以及如何使用它来更改 GDM 登录屏幕的各个方面。不用说，你必须使用 GNOME 桌面环境和 GDM 显示管理器才能按照此处的说明进行操作。? 以这种方式使用设置可能会产生问题。请使用 Timeshift 备份系统设置。如果你容易手忙脚乱，不喜欢排除故障，这篇文章就不适合你。使用 GDM 设置工具进行调整让我们首先看看你可以使用这个很棒的程序进行哪些更改。1、更改 shell 主题、图标和壁纸你可以更改登录屏幕的主题、图标和壁纸。这是一个例子。要更改主题，你应该先下载它。可以从 GNOME Look 网站 获取一个。接下来，确保主题位于 /usr/share/themes 中。存储在 ~/.themes 中的主题对 GDM 设置应用是不可见的。在 GDM 设置应用中，转到 “ 外观 Appearance ” 选项卡并选择 “ 主题 Themes ”（Shell/图标/光标）。如果要设置壁纸，请将 “ 背景 Background ” 更改为 “ 图像 Image ”，然后从文件浏览器浏览图片。完成后，单击 “ 应用 Apply ”。这将要求输入密码。请在出现提示时提供。你将收到注销通知以应用更改。注销后，更改将可见。? 你可以更改所有设置然后单击“应用”，或者每次设置后单击“应用”。如果按“应用”，则会提示你注销，每次都需要重新登录并再次打开该设置应用。2、更改字体在更改字体之前，你需要为所有用户在系统上安装该字体。为了确保这一点，请将下载的自定义字体文件粘贴到 /usr/local/share/fonts，然后使用以下命令创建字体缓存：fc-cache -f -v 现在，打开 GDM 设置并转到“ 字体 Fonts ”选项卡。在那里，你可以设置字体、抗锯齿设置等。你可以看到新字体现已设置为你的登录屏幕。3、更改顶部面板的颜色要更改顶部面板颜色，请转到侧栏中的 “ 顶部栏 Top Bar ” 选项。在 “ 调整 Tweaks ” 下，启用 “ 更改背景颜色 Change Background Color ” 按钮，然后设置所需的颜色。将顶部栏的文本颜色更改为适合你选择的背景的颜色也同样重要。4、更改时间显示格式使用下拉菜单将时钟更改为 24 小时或 12 小时格式。此外，你可以通过切换相应的按钮使秒在顶部栏上可见。5、启用登录屏幕轻击在大多数发行版中，这是默认行为。即使在系统中启用了轻击，GNOME 登录界面也需要使用鼠标左键点击。要更改此设置，请转到鼠标和触摸板部分并启用 “ 轻击 Tap to Click ” 按钮。在同一菜单上，你可以选择调整鼠标光标大小（如果你觉得它很小）。6、启用夜灯你可以为 GDM 启用预定的夜灯。转到 “ 显示 Display ”，打开 “ 夜灯 Night Light ” 按钮。现在，安排日落到日出或你选择的方便时间。7、添加徽标和欢迎消息转到 “ 登录屏幕 Login Screen ” 选项卡，然后启用 “ 启用徽标 Enable Logo ” 按钮。这将为你提供一个浏览图像的按钮。选择图像并按 “ 应用 Apply ”。? 在我的系统显示器上，尺寸高达 128×128 像素的图像看起来是可以接受的，超出这个尺寸对我来说看起来很大。因此，请相应地选择尺寸。应用图像后，要设置欢迎消息，请启用欢迎消息按钮，然后添加你想要显示的文本。当你选择用户输入密码时，将显示该消息。8、导出和导入设置如果你想在其他系统上应用相同的设置，你可以导出设置并将其导入到运行 GDM 设置工具的其他系统上。单击左上角的菜单，然后选择 “ 导出到文件 Export to file ”。将文件命名为 “.ini” 并将其保存在安全的地方。你可以稍后导入。9、重置所有设置不喜欢你所做的更改？ 有一个简单的方法可以恢复默认值。要重置调整，请单击左上角的菜单并选择 “ 重置设置 Reset settings ”。现在，按 “ 应用 Apply ”。它会询问你的密码。提供后，系统将提示你注销。你可以看到，所有更改均已恢复。10、更多设置还有其他可用的调整，例如：通过 “ 顶栏 Top Bar ⇾ 电源 Power ⇾ 显示电池百分比 Show Battery Percentage ”，在顶栏显示电池百分比。通过 “ 登录屏幕 Login Screen ⇾ 禁用用户列表 Disable User List ”，在登录屏幕上禁用或启用用户列表。通过 “ 电源 Power ” 选项卡更改屏幕关闭时间、暂停时间和其他电源设置。安装 GDM 设置工具既然你知道该工具可以进行哪些调整，你可能想自己尝试一下。让我们看看如何安装它。? 在 Ubuntu / Pop!\_OS 上，GDM 设置工具对我不起作用。我在 Debian 12 Bookworm 上以 Flatpak 应用使用。GDM 设置工具可以作为 Flatpak 安装。flatpak install flathub io.github.realmazharhussain.GdmSettings 或者，它可以作为 AppImage 提供。对于 Arch Linux 用户，请使用 AUR 中的任何 AUR 助手进行安装。yay -S gdm-settings 结论登录屏幕并不是每个人都可以定制的。除了“轻击”更改之外，大多数其他更改都只是外观更改。总的来说，对于喜欢自定义设置的每个角落的人们来说，有这样的选择是件好事。?️ 你是那些痴迷于定制的 Linux 用户之一吗？ 你会尝试 GDM 设置工具吗？（题图：DA/fb8961d0-852d-4d89-b5b2-d2912b38f6f8）via: https://itsfoss.com/customize-gdm-login/作者：Sreenath 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
Kate（KDE Advanced Text Editor）是一款自由开源的文本编辑器，适用于 Linux、Windows 和 macOS。对于文档编写者来说，Kate 集成的 Git 功能可以帮助简化编写过程。你无需记住 Git 命令，也无需在每次更改文件或切换分支时在终端中输入它们。本文重点为从事各种 Fedora 文档仓库的贡献者介绍 Kate 的主要功能。这些功能可以扩展到其他文档仓库。将 Kate 与你的仓库一起使用的准备工作将 SSH 密钥添加到 Pagure、GitLab 或 GitHub 上的帐户设置中。在 Pagure 上，转到 我的设置 My Settings – SSH 密钥 SSH Keys – 添加 SSH 密钥 Add SSH Key 在 GitLab 上， 首选项 Preferences – 用户设置 User Settings – 添加 SSH 密钥 Add an SSH Key 在 GitHub 上， 设置 Settings – SSH 和 GPG 密钥 SSH and GPG keys – 新的 SSH 密钥 New SSH key 复刻项目：转到上游仓库并选择 “ 复刻 Fork ” 按钮克隆仓库在你的分叉仓库中，选择 “ 使用 SSH 克隆 Clone with SSH ”。接下来，将该链接复制到剪贴板并将其粘贴到终端中的 GIT URL 中。克隆仓库时，你可以指定新目录名称作为附加参数。$ git clone <GIT URL> 新目录安装 Kate。如果你是 Linux 用户，请转到发行版的包管理器来安装 Kate。如果你使用 Fedora Linux，我们推荐 Fedora Linux RPM 版本或 Flatpak。会话Kate 文本编辑器中的会话功能可以将单独的项目分组在一起，并帮助你在单个视图中处理多个文档仓库。要将仓库保存在会话中：转到 “ 文件 File ” 下拉菜单 – 选择 “ 打开文件夹 Open folder ” – 选择克隆的目录。从 “ 会话 Sessions ” 下拉菜单中 – 选择 “ 保存会话 Save session ” – 输入会话名称 – 按 “ 确定 OK ”。在左侧窗格中，单击 “ 项目列表 project list ” 保存到新会话“Magazine”。下次打开 Kate 时，保存到会话中的克隆仓库将重新出现。使用状态栏签出分支使用 Kate 编辑器，你可以在状态栏和弹出屏幕上切换分支或创建新分支。当前分支显示在状态栏的右下角。要创建新分支，请选择 “Main” 分支。从弹出菜单中选择 “ 创建新分支 Create New Branch ” 并输入新分支名称。对 AsciiDoc 高亮显示的内置支持具有 AsciiDoc 扩展名的文件将使用 asciidoc.xml 中的规则自动高亮显示。你不需要安装外部插件。即时拼写检查如果你希望在输入时自动进行拼写检查，请按 Ctrl + Shift + O。此组合键将打开和关闭拼写检查。Git 工具视图左侧窗格中的工具视图显示每个打开文件的 Git 状态。“ 已暂存 Staged ” 表示文件已添加（与 Git 添加相同），并且如果你选择顶部的 “ 提交 Commit ” 按钮，文件将被提交。“ 已修改 Modified ” 显示尚未暂存的更改。单击左侧面板顶部的 “ 提交 Commit ” 按钮以显示该提交的差异。这将在提交工具视图中打开选定的提交。如果你想查看提交中的所有更改，请右键单击并选择 “ 显示完整提交 Show Full Commit ”，添加一个提交消息。Git “ 推送 Push ” 按钮在 “ 提交 Commit ” 按钮的右边。Git “ 拉取 Pull ” 按钮在 “ 推送 Push ” 按钮的右边。选择 “ 刷新 Refresh ” 图标（圆圈箭头）以查看暂存文件和提交的情况。集成终端按 F4 或选择 “ 终端 Terminal ” 按钮可打开和关闭集成终端。你可以通过集成终端使用构建脚本和 Vale linter，将你的写作提升到一个新的水平，确保文档质量。步骤 1. 运行构建脚本要在本地检查文档质量，你可以在集成终端中运行构建和预览脚本。构建和预览脚本可让你准确查看更改如何通过 Antora 静态站点生成器在文档页面中发布。注意：检查 Fedora 文档仓库的 README 页面，为构建脚本和说明使用正确的文件名。下面是一个例子：要构建和预览站点，请运行：$ ./docsbuilder.sh -p 结果可访问 http://localhost:8080要停止预览：$ ./docsbuilder.sh -k 步骤 2. 对你的文本运行 ValeVale 是一个命令行工具，用于检查文本是否符合定义的样式指南。参考该 指南 在本地运行 Vale。鸣谢非常感谢 KDE 开发人员 Nicco，他的视频教程频道 “Nicco loves Linux” 给了我很多灵感。本文使用的 Kate 版本为 23.08.3上游文档以下是本文使用的 Fedora 文档 Git 仓库：快速文档Kinoite 用户文档IoT 用户文档文档贡献者指南（题图：DA/519568d2-a224-4075-a751-a1a8bc702079）via: https://fedoramagazine.org/writing-docs-with-kate-and-git/作者：Hank Lee 选题：lujun9972 译者：geekpi 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出
大家好！我一直在慢慢摸索如何解释 Git 中的各个核心理念（提交、分支、远程、暂存区），而提交这个概念却出奇地棘手。要明白 Git 提交是如何实现的对我来说相当简单（这些都是确定的！我可以直接查看！），但是要弄清楚别人是怎么看待提交的却相当困难。所以，就像我最近一直在做的那样，我在 Mastodon 上问了一些问题。大家是怎么看待 Git 提交的？我进行了一个 非常不科学的调查，询问大家是怎么看待 Git 提交的：是快照、差异，还是所有之前提交的列表？（当然，把它看作这三者都是合理的，但我很好奇人们的 主要 观点）。这是调查结果：结果是：51% 差异42% 快照4% 所有之前的提交的历史记录3% “其他”我很惊讶差异和快照两个选项的比例如此接近。人们还提出了一些有趣但相互矛盾的观点，比如 “在我看来，提交是一个差异，但我认为它实际上是以快照的形式实现的” 和 “在我看来，提交是一个快照，但我认为它实际上是以差异的形式实现的”。关于提交的实际实现方式，我们稍后再详谈。在我们进一步讨论之前：我们的说 “一个差异” 或 “一个快照” 都是什么意思？什么是差异？我说的“差异”可能相当明显：差异就是你在运行 git show COMMIT_ID 时得到的东西。例如，这是一个 rbspy 项目中的拼写错误修复：diff --git a/src/ui/summary.rs b/src/ui/summary.rs index 5c4ff9c..3ce9b3b 100644 --- a/src/ui/summary.rs +++ b/src/ui/summary.rs @@ -160,7 +160,7 @@ mod tests { "; let mut buf: Vec<u8> = Vec::new(); - stats.write(&mut buf).expect("Callgrind write failed"); + stats.write(&mut buf).expect("summary write failed"); let actual = String::from_utf8(buf).expect("summary output not utf8"); assert_eq!(actual, expected, "Unexpected summary output"); } 你可以在 GitHub 上看到它： https://github.com/rbspy/rbspy/commit/24ad81d2439f9e63dd91cc1126ca1bb5d3a4da5b什么是快照？我说的 “快照” 是指 “当你运行 git checkout COMMIT_ID 时得到的所有文件”。Git 通常将提交的文件列表称为 “树”（如“目录树”），你可以在 GitHub 上看到上述提交的所有文件：https://github.com/rbspy/rbspy/tree/24ad81d2439f9e63dd91cc1126ca1bb5d3a4da5b（它是 /tree/ 而不是 /commit/）“Git 是如何实现的”真的是正确的解释方式吗？我最常听到的关于学习 Git 的建议大概是 “只要学会 Git 在内部是如何表示事物的，一切都会变得清晰明了”。我显然非常喜欢这种观点（如果你花了一些时间阅读这个博客，你就会知道我 喜欢 思考事物在内部是如何实现的）。但是作为一个学习 Git 的方法，它并没有我希望的那么成功！通常我会兴奋地开始解释 “好的，所以 Git 提交是一个快照，它有一个指向它的父提交的指针，然后一个分支是一个指向提交的指针，然后……”，但是我试图帮助的人会告诉我，他们并没有真正发现这个解释有多有用，他们仍然不明白。所以我一直在考虑其他方案。但是让我们还是先谈谈内部实现吧。Git 是如何在内部表示提交的 —— 快照在内部，Git 将提交表示为快照（它存储每个文件当前版本的 “树”）。我在 在一个 Git 仓库中，你的文件在哪里？ 中写过这个，但下面是一个非常快速的内部格式概述。这是一个提交的表示方式：$ git cat-file -p 24ad81d2439f9e63dd91cc1126ca1bb5d3a4da5b tree e197a79bef523842c91ee06fa19a51446975ec35 parent 26707359cdf0c2db66eb1216bf7ff00eac782f65 author Adam Jensen <adam@acj.sh> 1672104452 -0500 committer Adam Jensen <adam@acj.sh> 1672104890 -0500 Fix typo in expectation message 以及，当我们查看这个树对象时，我们会看到这个提交中仓库根目录下每个文件/子目录的列表：$ git cat-file -p e197a79bef523842c91ee06fa19a51446975ec35 040000 tree 2fcc102acd27df8f24ddc3867b6756ac554b33ef .cargo 040000 tree 7714769e97c483edb052ea14e7500735c04713eb .github 100644 blob ebb410eb8266a8d6fbde8a9ffaf5db54a5fc979a .gitignore 100644 blob fa1edfb73ce93054fe32d4eb35a5c4bee68c5bf5 ARCHITECTURE.md 100644 blob 9c1883ee31f4fa8b6546a7226754cfc84ada5726 CODE_OF_CONDUCT.md 100644 blob 9fac1017cb65883554f821914fac3fb713008a34 CONTRIBUTORS.md 100644 blob b009175dbcbc186fb8066344c0e899c3104f43e5 Cargo.lock 100644 blob 94b87cd2940697288e4f18530c5933f3110b405b Cargo.toml 这意味着检出一个 Git 提交总是很快的：对 Git 来说，检出昨天的提交和检出 100 万个提交之前的提交一样容易。Git 永远不需要重新应用 10000 个差异来确定当前状态，因为提交根本就不是以差异的形式存储的。快照使用 packfile 进行压缩我刚刚提到了 Git 提交是一个快照，但是，当有人说 “在我看来，提交是一个快照，但我认为它在实现上是一个差异” 时，这其实也是对的！Git 提交并不是以你可能习惯的差异的形式表示的（它们不是以与上一个提交的差异的形式存储在磁盘上的），但基本的直觉是，如果你要对一个 10,000 行的文件编辑 500 次，那么存储 500 份文件的效率会很低。Git 有一个将文件以差异的形式存储的方法。这被称为 “packfile”，Git 会定期进行垃圾回收，将你的数据压缩成 packfile 以节省磁盘空间。当你 git clone 一个仓库时，Git 也会压缩数据。这里，我没有足够的篇幅来完整地解释 packfile 是如何工作的（Aditya Mukerjee 的 《解压 Git packfile》是我最喜欢的解释它们是如何工作的文章）。不过，我可以在这里简单总结一下我对 deltas 工作原理的理解，以及它们与 diff 的区别：对象存储为 “原始文件” 和一个 “ 变化量 delta ” 的引用变化量是一系列例如 “读取第 0 到 100 字节，然后插入字节 ‘hello there’，然后读取第 120 到 200 字节” 的指令。它从原始文件中拼凑出新的文本。所以没有 “删除” 的概念，只有复制和添加。我认为变化量的层次较少：我不知道如何检查 Git 究竟要经过多少层变化量才能得到一个给定的对象，但我的印象是通常不会很多。可能少于 10 层？不过，我很想知道如何才能真正查出来。原始文件不一定来自上一个提交，它可以是任何东西。也许它甚至可以来自一个更晚的提交？我不确定。没有一个 “正确的” 算法来计算变化量，Git 只是有一些近似的启发式算法当你查看差异时，实际上发生了一些奇怪的事情当我们运行 git show SOME_COMMIT 来查看某个提交的差异时，实际上发生的事情有点反直觉。我的理解是：Git 会在 packfile 中查找并应用变化量来重建该提交和其父提交的树。Git 会对两个目录树（当前提交的目录树和父提交的目录树）进行差异比较。通常这很快，因为几乎所有的文件都是完全一样的，所以 git 只需比较相同文件的哈希值就可以了，几乎所有时候都不用做什么。最后 Git 会展示差异所以，Git 会将变化量转换为快照，然后计算差异。它感觉有点奇怪，因为它从一个类似差异的东西开始，最终得到另一个类似差异的东西，但是变化量和差异实际上是完全不同的，所以这是说得通的。也就是说，我认为 Git 将提交存储为快照，而 packfile 只是一个实现细节，目的是节省磁盘空间并加快克隆速度。我其实从来没必要知道 packfile 是如何工作的，但它确实能帮助我理解 Git 是如何在不占用太多磁盘空间的情况下将提交快照化的。一个 “错误的” Git 理解：提交是差异我认为一个相当常见的，对 Git 的 “错误” 的理解是：提交是以基于上一个提交的差异的形式存储的（加上指向父提交的指针和作者和消息）。要获取提交的当前状态，Git 需要从头开始重新应用所有之前的提交。这个理解当然是错误的（在现实中，提交是以快照的形式存储的，差异是从这些快照计算出来的），但是对我来说它似乎非常有用而且有意义！在考虑合并提交时会有一点奇怪，但是或许我们可以说这只是基于合并提交的第一个父提交的差异。我认为这个错误的理解有的时候非常有用，而且对于日常 Git 使用来说它似乎并没有什么问题。我真的很喜欢它将我们最常使用的东西（差异）作为最基本的元素——它对我来说非常直观。我也一直在思考一些其他有用但 “错误” 的 Git 理解，比如：提交信息可以被编辑（实际上不能，你只是复制了一个相同的提交然后给了它一个新的信息，旧的提交仍然存在）提交可以被移动到一个不同的基础上（类似地，它们是被复制了）我认为有一系列非常有意义的、 “错误” 的对 Git 的理解，它们在很大程度上都受到 Git 用户界面的支持，并且在大多数情况下都不会产生什么问题。但是当你想要撤销一个更改或者出现问题时，它可能会变得混乱。将提交视为差异的一些优势就算我知道在 Git 中提交是快照，我可能大部分时间也都将它们视为差异，因为：大多时候我都在关注我正在做的 更改 —— 如果我只是改变了一行代码，显然我主要是在考虑那一行代码而不是整个代码库的当前状态点击 GitHub 上的 Git 提交或者使用 git show 时，你会看到差异，所以这只是我习惯看到的东西我经常使用变基，它就是关于重新应用差异的将提交视为快照的一些优势但是我有时也会将提交视为快照，因为：Git 经常对文件的移动感到困惑：有时我移动了一个文件并编辑了它，Git 无法识别它是否被移动过，而是显示为 “删除了 old.py，添加了 new.py”。这是因为 Git 只存储快照，所以当它显示 “移动 old.py -> new.py” 时，只是猜测，因为 old.py 和 new.py 的内容相似。这种方式更容易理解 git checkout COMMIT_ID 在做什么（重新应用 10000 个提交的想法让我感到很有压力）合并提交在我看来更像是快照，因为合并的提交实际上可以是任何东西（它只是一个新的快照！）。它帮助我理解为什么在解决合并冲突时可以进行任意更改，以及为什么在解决冲突时要小心。其他一些关于提交的理解Mastodon 的一些回复中还提到了：有关提交的 “额外的” 带外信息，比如电子邮件、GitHub 拉取请求或者你和同事的对话将“差异”视为一个“之前的状态 + 之后的状态”以及，当然，很多人根据情况的不同以不同的方式看待提交人们在谈论提交时使用的其他一些词可能不那么含糊：“修订”（似乎更像是快照）“补丁”（看起来更像是差异）就到这里吧！我很难了解人们对 Git 有哪些不同的理解。尤其棘手的是，尽管 “错误” 的理解往往非常有用，但人们却非常热衷于警惕 “错误” 的心智模式，所以人们不愿意分享他们 “错误” 的想法，生怕有什么 Git 解释者会站出来向他们解释为什么他们是错的。（这些 Git 解释者通常是出于善意的，但是无论如何它都会产生一种负面影响）但是我学到了很多！我仍然不完全清楚该如何谈论提交，但是我们最终会弄清楚的。感谢 Marco Rogers、Marie Flanagan 以及 Mastodon 上的所有人和我讨论 Git 提交。（题图：DA/cc0cada9-4945-4248-8635-3f89dcebd6ef）via: https://jvns.ca/blog/2024/01/05/do-we-think-of-git-commits-as-diffs--snapshots--or-histories/作者：Julia Evans 选题：lujun9972 译者：Cubik65536 校对：wxy本文由 LCTT 原创编译，Linux中国 荣誉推出