跳到主要内容

Go type 关键字的使用

· 阅读需 2 分钟
素明诚
Full stack development

定义结构体(Struct)

使用场景:当你需要定义一个复合数据类型来组织和存储不同类型的数据时,结构体非常有用。它们通常用于模拟现实世界中的对象和实体

type Employee struct {
ID int
FirstName string
LastName string
Address string
}

定义接口(Interface)

使用场景:接口在为不同的类型提供统一的方法集合方面非常有用。它们广泛用于实现多态性和封装概念,使得你可以编写更灵活和可扩展的代码

type Reader interface {
Read(p []byte) (n int, err error)
}

定义类型别名(Type Alias)

使用场景:类型别名主要用于代码重构,特别是在将一个大型项目从一个 API 迁移到另一个兼容的 API 时,它可以确保向后兼容

type OldLogger = NewLogger

定义自定义类型(Custom Type)

使用场景:自定义类型适用于为特定的数据或概念创建专有的类型,这样可以使代码更加清晰易懂,并且利于类型安全

type UserID int

定义函数类型(Function Type)

使用场景:当你需要将函数作为参数传递给其他函数,或者需要从函数返回函数时,定义函数类型非常有用。这有助于创建高度模块化和可重用的代码库

type HandlerFunc func(w http.ResponseWriter, r *http.Request)

Go 带 和 不带 的结构体的区别

· 阅读需 3 分钟
素明诚
Full stack development

不带*(直接使用结构体实例)

当你直接使用结构体实例时,每次你将结构体赋值给另一个变量或将其作为参数传递给函数时,Go 都会创建该结构体的一个副本。

type Person struct {
Name string
Age int
}

func incrementAge(p Person) {
p.Age += 1 // 只修改了副本的Age
}

func main() {
person := Person{Name: "John", Age: 30}
incrementAge(person)
fmt.Println(person.Age) // 输出: 30,因为incrementAge中修改的是person的副本
}

在这个例子中,即使incrementAge函数尝试修改PersonAge,主函数中的person变量也不会受到影响,因为它操作的是person的一个副本。

带*(使用指向结构体的指针)

当你使用指向结构体的指针时,你可以直接修改原始结构体实例中的数据,因为指针存储的是结构体数据的内存地址。

func incrementAge(p *Person) {
p.Age += 1 // 直接修改原始结构体实例的Age
}

func main() {
person := Person{Name: "John", Age: 30}
incrementAge(&person)
fmt.Println(person.Age) // 输出: 31,因为incrementAge中修改的是原始person实例
}

在这个例子中,incrementAge函数接收一个指向Person的指针,这意味着它可以直接修改传递给它的实例。当我们传递&personperson的地址)给incrementAge,函数中的任何修改都会反映在main函数中的person上。

那修改的是哪个实例?

修改的是在函数incrementAge调用时传入的person实例的副本。这个副本只在incrementAge函数的作用域内存在,一旦incrementAge函数执行完毕,这个副本就会被丢弃(如果没有其他引用指向它,它会被垃圾回收器回收)。因此,incrementAge函数内部对p.Age的修改不会影响到main函数中的person实例。

为什么设计成这样?

  1. Go 语言在函数调用时通过值传递的方式避免对原始数据的不必要修改,从而保持数据的安全性和一致性。同时,这种方式也避免了在函数调用时不断修改原始数据可能导致的错误和混乱。
  2. 通过值传递,函数接收的是数据副本,这确保了函数的纯粹性(尤其是对于简单函数而言),函数的行为不会因为外部变量的改变而改变,使得函数更易于理解和预测。
  3. 比如对于大型结构体,复制整个结构体可能会导致额外的内存和性能开销。因此,在处理大型数据或需要直接修改原始数据时,使用指针传递会更高效。所以,遇事不决就使用指针就对了。

人工智能 常见术语和概念

· 阅读需 7 分钟
素明诚
Full stack development
术语解释
AI(人工智能)指模拟人类智能的技术,使机器能够执行需要人类智能的任务,如学习、推理、自我修正等。
ML(机器学习)AI 的一个分支,指让机器通过数据学习并做出预测或决策的方法,而无需明确编程。
DL(深度学习)机器学习的一个子集,使用被称为神经网络的算法,尤其是深层神经网络,从大量数据中学习。
NLP(自然语言处理)使计算机能够理解、解释和生成人类语言的 AI 分支。
CV(计算机视觉)使计算机能够从图像或多维数据中理解和解释视觉信息的科学。
ANN(人工神经网络)由相互连接的节点或神经元组成的计算系统,模拟人脑解决问题。
CNN(卷积神经网络)一种深度学习算法,特别适用于处理具有网格结构的数据,如图像。
RNN(循环神经网络)一种处理序列数据的神经网络,能够利用其内部状态(记忆)处理输入序列。
GAN(生成对抗网络)由两个神经网络组成,通过相互对抗来提高生成的数据质量。
RL(强化学习)一种让机器通过试错来学习特定任务的最佳策略的算法。
BERT(双向编码器表示从 Transformer)一个预训练 NLP 模型,用于理解自然语言文本。
GPT(生成预训练 Transformer)一个自然语言处理模型,专注于生成文本。
Transformer一种深度学习模型,广泛用于处理序列数据,尤其是在 NLP 领域。
RAG(检索增强生成)结合了检索和生成的技术,用于提升自然语言生成的准确性和相关性。
Zero-shot learning学习模型如何在没有见过任何训练数据的情况下解决任务的能力。
Few-shot learning指让模型仅使用极少量的训练样本来学习任务的能力。
术语解释
LSTM(长短期记忆)一种特殊的 RNN,能够学习长期依赖信息,常用于序列数据的处理。
GRU(门控循环单元)LSTM 的一种变体,用于序列数据的建模,但结构更简单。
Autoencoder一种无监督的神经网络,用于数据编码的有效表示。
Reinforcement Learning一种机器学习方法,通过奖励和惩罚机制来训练模型。
Supervised Learning一种机器学习任务,模型从标注数据中学习。
Unsupervised Learning一种机器学习任务,模型从未标注数据中学习。
Semi-supervised Learning介于监督学习和无监督学习之间,模型从部分标注的数据中学习。
Transfer Learning将从一个任务学到的知识应用到另一个相关任务的方法。
Federated Learning一种机器学习设置,模型在多个边缘设备上分布式训练,不共享数据。
Attention Mechanism使模型能够在处理信息时,关注到更重要部分的技术。
Transformer一种基于自注意力机制的模型架构,广泛用于处理序列数据。
Sequence-to-Sequence一种模型架构,用于将一个序列转换为另一个序列,如机器翻译。
Word Embedding将单词或短语从词汇表映射到向量的一种技术。
Entity Recognition从文本中识别具有特定意义的实体(如人名、地点等)。
Sentiment Analysis确定文本的情感倾向,如正面、负面或中性。
Chatbots设计用于模拟人与人之间对话的 AI 系统。
Generative Models能够生成新数据实例的模型,如 GAN。
Bias and Variance机器学习模型的两种主要误差来源,偏差与方差。
Hyperparameter Tuning选择一组最优的超参数,以提高模型的性能。
Cross-validation一种评估模型性能的技术,通过在不同的数据子集上训练和测试模型。
Natural Language Understanding (NLU)让计算机理解、解释和生成人类语言的过程。
Natural Language Generation (NLG)自动生成人类语言文本的过程。
Object Detection在图像中识别对象的位置及类别的技术。
Image Segmentation将图像分割成多个部分或对象的过程。
Edge Computing数据在产生源头附近处理,而不是在中心或云中处理。
术语解释
Multi-task Learning一种学习策略,旨在同时解决多个相关任务,共享表示以提高效率和性能。
Anomaly Detection识别数据集中的异常或不寻常模式的过程。
Dimensionality Reduction减少数据集中变量数量的过程,用于提高算法效率并改善性能。
Feature Engineering创建新的输入特征或修改现有特征以提高机器学习模型性能的过程。
Ensemble Learning结合多个模型来改善预测性能的技术,如随机森林和梯度提升。
Overfitting一个模型在训练数据上学得太好,以至于泛化到新数据上时性能下降。
Underfitting模型无法在训练数据上获得足够的学习,也无法捕捉数据的基本结构。
Precision and Recall在分类任务中,精确度和召回率是衡量模型性能的重要指标。
F1 Score精确度和召回率的调和平均数,用于衡量模型的整体性能。
Regularization一种减少模型过拟合的技术,通过添加一个惩罚项到损失函数。
Activation Functions在神经网络中,激活函数决定了一个节点是否应该被激活,帮助网络学习复杂的模式。
Backpropagation一种训练人工神经网络的算法,通过计算损失函数相对于网络参数的梯度来更新权重。
Data Augmentation通过对原始数据进行变化生成新数据的技术,以增强模型的泛化能力。
Model Deployment将训练好的模型部署到生产环境中,以便对新数据做出预测。
Ethics in AI讨论和指导人工智能的发展和应用,确保技术被负责任地使用的原则和标准。
Explainable AI (XAI)提高机器学习模型的可解释性,以便人类理解模型的决策过程。
Data Imbalance在数据集中,一些类别的样本远多于其他类别,可能影响模型性能。
Synthetic Data通过算法生成的数据,用于训练模型,特别是在真实数据不足或难以获取的情况下。
Bias in AI指模型在预测时系统性偏离真实值,可能由不平衡的数据或错误的模型假设引起。
Meta-learning也称为“学习如何学习”,旨在设计模型能够快速适应新任务的技术。
Reinforcement Learning通过与环境的交互,采取行动以最大化某种累积奖励的学习方法。
Graph Neural Networks (GNNs)用于处理图结构数据的神经网络,如社交网络、分子结构等。
Quantum Machine Learning结合量子计算和机器学习,以期在特定任务上提供超越传统算法的性能。
Bias-Variance Tradeoff描述模型复杂度与泛化能力之间的关系,
标签:

为什么说英语天然分词而中文不是

· 阅读需 2 分钟
素明诚
Full stack development

说英语“天然分词”而中文不是,主要是因为英语和中文在书写和语法结构上的差异。

英语的“天然分词”

英语作为一种印欧语系的语言,其书写系统中单词之间通常由空格分隔。这种空格不仅在视觉上标示了单词的边界,也使得词汇的识别和分割变得相对直观和简单。因此,在处理英文文本时,简单地按空格分割基本上就可以得到有效的单词列表,这就是所谓的“天然分词”。

中文的分词挑战

中文属于汉藏语系,其书写系统中的文字是紧密连续的,没有明显的分隔符来直接标示词语的边界。中文的“词”是由一个或多个汉字组成的,汉字之间没有空格或其他明显的分隔符。因此,从连续的文本中确定哪些汉字组合在一起形成有意义的词汇是中文自然语言处理中的一个基本而重要的任务。这个过程称为“分词”。

为什么分词很重要

在自然语言处理(NLP)中,无论是英语还是中文,分词都是一个基础且关键的步骤。它直接影响到后续的词性标注、命名实体识别、情感分析等任务的效果。对于中文来说,准确的分词更是挑战性的,因为:

  • 同一串汉字在不同上下文中可能有不同的切分方式,这就需要理解上下文来做出正确的分词决策。
  • 存在大量的歧义和新词,这些都需要分词系统能够不断更新和学习来适应语言的变化。

因此,虽然英语由于其书写系统的特点在分词方面面临的挑战相对较小,中文的分词则需要复杂的算法和大量的语料库支持,才能有效地识别词汇边界,处理歧义等问题。

标签:

数据向量化的方式

· 阅读需 4 分钟
素明诚
Full stack development

数值数据

原始数据:人的身高 175cm,体重 70kg。

向量化后:175,70175,70。

这里直接使用数值作为向量的元素。

类别数据

原始数据:颜色,选项有“红、黄、蓝”。

  • 如果某个对象的颜色是“红”,

向量化后:1,0,01,0,0。

  • 如果颜色是“黄”,

向量化后:0,1,00,1,0。

这种方法称为独热编码,每个位置代表一种颜色,该位置为 1 则表示该颜色,其他位置为 0。

文本数据

原始数据:"The cat sat on the mat."

  • 词袋模型(Bag of Words):
    向量化后:假设字典中的词有 "the", "cat", "sat", "on", "mat", "dog",则向量可能为 2,1,1,1,1,02,1,1,1,1,0,表示字典中每个词在文本中出现的次数。
  • TF-IDF:
    向量化后:每个元素是一个词的 TF-IDF 得分,例如 0.3,0.2,0.2,0.2,0.2,00.3,0.2,0.2,0.2,0.2,0,数值表示词的重要性。

图像数据

原始数据:一个 8x8 像素的黑白图像。

向量化后:每个像素值在 0 到 255 之间,将图像展平为一个 64 维的向量 0,255,122,...,430,255,122,...,43。

时间序列数据

原始数据:一周的股票价格 100,102,104,103,105,107,108100,102,104,103,105,107,108。

向量化后:直接使用这个序列作为向量 100,102,104,103,105,107,108100,102,104,103,105,107,108,或者提取特征如平均价格、最大增长率等。

声音和视频数据的向量化稍微复杂一些,因为它们是时间序列数据的多维表示,通常包含大量的信息。下面是声音和视频数据向量化的一些方法和例子。

声音数据

声音数据通常以波形的形式出现,可以通过多种方法向量化,用于后续的处理和分析。

原始数据:一段音频记录。

  • 时域分析:直接使用音频的原始波形数据。例如,一段音频文件的振幅值可以直接构成一个向量。
    向量化后:0.01,−0.02,0.03,...,−0.010.01,−0.02,0.03,...,−0.01,这些数值代表音频波形在不同时间点的振幅。
  • 频域分析(傅立叶变换):将音频信号从时域转换到频域,表示为不同频率成分的强度。
    向量化后:5,20,0,3,...,85,20,0,3,...,8,这里每个数值代表了音频中对应频率成分的强度。
  • MFCC(梅尔频率倒谱系数):一种在语音识别中常用的特征,它描述了音频信号的短时功率谱在梅尔尺度上的对数。
    向量化后:13,−3,2,5,...,713,−3,2,5,...,7,一组 MFCC 系数可以作为音频的特征向量。

视频数据

视频是一系列连续图像帧的集合,通常还伴有音频轨。因此,视频数据的向量化需要考虑空间信息(图像帧)和时间信息(帧序列)。

原始数据:一段视频。

  • 帧提取:将视频分解为一系列图像帧,每一帧可以像处理静态图像那样被向量化。例如,可以使用前面提到的图像数据向量化方法。
    向量化后:图像帧 1 的向量,图像帧 2 的向量,...图像帧 1 的向量,图像帧 2 的向量,...,视频变成了一系列图像帧向量的集合。
  • 时间特征提取:除了提取每一帧的空间特征外,还可以提取表示视频时间演变特征的向量,如通过对连续帧的变化进行编码。
  • 深度学习方法:可以使用卷积神经网络(CNN)来处理单个图像帧,以及使用循环神经网络(RNN)或 3D 卷积网络来处理帧序列中的时间关系。
    向量化后:利用神经网络,视频可以被编码成一个高维的特征向量,用于视频分类、情感分析等任务。

复杂结构数据

原始数据:一个社交网络图。

向量化后(图嵌入):假设每个用户是图中的一个节点,使用图嵌入技术可能会得到每个用户的向量表示,如用户 A 的向量可能是 0.5,−0.1,0.30.5,−0.1,0.3,这个向量捕捉了用户在社交网络中的位置和连接模式

为什么说所有数据都可以向量化?

向量化的本质是提取数据的特征并用数值来表示这些特征。不同类型的数据,如文本、图像、声音等,虽然它们的特征提取方法和向量化技术各不相同,但最终都能归结为数值表示的形式。

标签:

GET 请求查询字符串和路径参数的区别

· 阅读需 2 分钟
素明诚
Full stack development

查询字符串(Query String)

GET /resource?id=2

  • 这是传统的方法,将参数添加到 URL 的查询字符串中。
  • 它适用于过滤结果或传递非层级性的数据。
  • 它使得参数可选,可以很容易地添加更多的参数,例如 GET /resource?id=2&sort=asc&category=books
  • 此方法在 URL 的长度和结构上可能有限制,因为有些浏览器和服务器对 URL 长度有限制。

路径参数(Path Parameter)或 RESTful 参数

GET /resource/2

  • 这种方法通常用于 RESTful API,参数是 URL 路径的一部分,前端更喜欢这种。
  • 它适用于指定资源或资源的特定操作,表达了一种层级关系。
  • URL 看起来更加清洁和“友好”,这有时候被称为“clean URLs”或“pretty URLs”。
  • 在设计 RESTful API 时,路径参数常用来获取特定资源或资源集合。

建议使用哪一种?

  • 如果你在设计一个RESTful API,通常会使用路径参数来获取特定资源。例如,GET /users/2 来获取 ID 为 2 的用户。
  • 如果你需要过滤列表或者有很多可选的参数,那么查询字符串可能更合适。例如,GET /users?id=2 可以用来从用户集合中过滤出 ID 为 2 的用户,同时还能添加其他过滤选项,如 GET /users?role=admin

阻止允许 浏览器自动填充密码

· 阅读需 1 分钟
素明诚
Full stack development

autocomplete="new-password"

始终告诉浏览器这是新密码

<el-input
v-model="userForm.password"
class="loginInput"
type="password"
autocomplete="new-password"
show-password
placeholder="设置登录密码(数字+字母,8位以上)"
size="large"
@keydown.enter="loginVerification">
</el-input>

autocomplete="current-password"

告诉浏览器要记住密码

<el-input
v-model="userForm.password"
class="loginInput"
type="password"
autocomplete="current-password"
show-password
placeholder="请输入登录密码"
size="large"
@keydown.enter="loginVerification">
</el-input>

autocomplete="tel"

指定自动填充某些字段,该例子为字段填充手机号

<el-input
v-model="smsForm.mobilePhone"
class="loginInput mb20 mobilePhoneNumber"
placeholder="请输入手机号"
clearable
size="large"
autocomplete="tel">
</el-input>

word 转 html 保留基本格式

· 阅读需 1 分钟
素明诚
Full stack development

需要用到这个库 mammoth.js

在项目中安装

npm install mammoth

运行脚本

const mammoth = require('mammoth');
const fs = require('fs');

mammoth
.convertToHtml({ path: './index.docx' })
.then(function (result) {
fs.writeFileSync('./output.html', result.value);
})
.catch(function (err) {
console.log(err);
});

转换后可以看到,很多格式都是保留下来的,更方便后期设置样式了

7fe23cd05beca1a32de3c3354f8a39c4

常用 go 命令

· 阅读需 1 分钟
素明诚
Full stack development
命令描述
go build编译 Go 程序。
go run编译并运行 Go 程序。
go test运行测试。
go get下载并安装包及其依赖。
go get -u更新包和依赖到最新版本。
go mod init初始化新的模块,创建 go.mod 文件。
go mod tidy添加缺失的模块,移除无用的模块。
go mod download下载 go.mod 文件中指明的所有依赖。
go mod verify验证依赖是否已下载且未修改。
go mod vendor将依赖复制到项目下的 vendor 目录中。
go list列出选定或全部的包。
go fmt格式化 Go 源代码。
go env打印 Go 的环境信息。
go clean移除对象文件和缓存文件。

get -u 注意

    • 如果直接运行 go get -u 而不指定具体的包,它将更新当前模块(项目)所有依赖的包到最新版本。这包括直接依赖和间接依赖。
    • 如果指定了具体的包,如 go get -u some/package,则只会更新该包及其依赖到最新版本。