【自然语言处理】Word2Vec 词向量模型详解 + Python代码实战

news2025/1/19 20:23:48

文章目录

  • 一、词向量引入
  • 二、词向量模型
  • 三、训练数据构建
  • 四、不同模型对比
    • 4.1 CBOW
    • 4.2 Skip-gram 模型
    • 4.3 CBOW 和 Skip-gram 对比
  • 五、词向量训练过程
    • 5.1 初始化词向量矩阵
    • 5.2 训练模型
  • 六、Python 代码实战
    • 6.1 Model
    • 6.2 DataSet
    • 6.3 Main
    • 6.4 运行输出


一、词向量引入

先来考虑一个问题:如何能将文本向量化呢?听起来比较抽象,我们可以先从人的角度来思考。

如何用一个数值向量描述一个人呢?只用身高或者体重,还是综合其各项指标呢?当然是综合各项指标能更加准确的描述一个人啦,具体什么指标还得看你能收集到什么指标。比如除了常规的身高、体重外,我们还可以用人的性格,从内向到外向设置为从-1到+1,人的性格让“专家”去打分,从而获取人性格的数值化数据。

只要有了向量,就可以用不同方法(欧氏距离、曼哈顿距离、切比雪夫距离、余弦相似度等)来计算两个向量之间的相似度了!

在这里插入图片描述
通常来说,向量的维度越高,能提供的信息也就越多,从而计算结果的可靠性就更值得信赖

在这里插入图片描述

现在回到正题,如何描述词的特征?通常都是在词的层面上来构建特征。Word2Vec就是要把词转化为向量。

下图展示了一个50维的词向量:

在这里插入图片描述
假设现在已经拿到了一份训练好的词向量,其中每一个词都表示为50维的向量,如下图所示:

在这里插入图片描述
如果将它们在热度图中显示,结果如下:

在这里插入图片描述
在结果中可以发现,相似的词在特征表达中比较相似,也就是说明词的特征是有实际意义的!

在这里插入图片描述


二、词向量模型

在词向量模型中输入和输出是什么?中间这个黑盒又是什么?

在这里插入图片描述

如下图所示,在词向量模型中,输入可以是多个词。例如下面所示的,输入是 Thou 和 shalt,模型的任务是预测它们的下一个词是什么。

最后一层连接了 SoftMax,所以网络的输出是所有词可能是下一个词的概率。

在这里插入图片描述

那么有人就会问了,输入是文字,文字怎么输入到神经网络中啊 ?这个问题很好,我们通常会用一个 Embedding 层来解决这个问题。如下图所示,在神经网络初始化的时候,我们会随机初始化一个 N×K 的矩阵,其中 N 是 词典的大小,K 是词向量的维数(一个自行设定的超参数)。然后,我们会用一个 N×N 的矩阵和 N×K 的矩阵相乘,得到一个新的 N×K的矩阵向下进行前向传播。其中,N×N 的矩阵会在输入的文字的对应对角线上设置为1,其余位置均为0。N×K 的矩阵是随机初始化的,通过反向传播进行更新调整。

在这里插入图片描述

下面展示了一个例子(假设输入的两个词在词典中的位置是2和3处):

在这里插入图片描述


三、训练数据构建

问:我们的训练数据应该从哪找呢?

答:一切具有正常逻辑的语句都可以作为训练数据。如小说、论文等。

在这里插入图片描述
如果我们有一个句子,那么我们可以按照下面你的方式构建数据集,选出前三个词,用前两个作为词模型的输入,最后一个词作为词模型输出的目标,继而进行训练。如下图所示:

在这里插入图片描述

然后,我们还可以将”窗口“往右平移一个词,如下图所示,构造一个新的训练数据

在这里插入图片描述
当然,这个”窗口“的宽度也是可以自己设置的,在上例中,窗口宽度设置为 3,也可以设置为 4、5、6 等等


四、不同模型对比

4.1 CBOW

CBOW的全称是continuous bag of words(连续词袋模型)。其本质也是通过context word(背景词)来预测target word(目标词)。

CBOW之所以叫连续词袋模型,是因为在每个窗口内它也不考虑词序信息,因为它是直接把上下文的词向量相加了,自然就损失了词序信息。CBOW抛弃了词序信息,指的就是在每个窗口内部上下文直接相加而没有考虑词序。

用 CBOW 构造数据集的例子如下图所示:

在这里插入图片描述

4.2 Skip-gram 模型

Skip-gram 模型和 CBOW 相反,Skip-gram 模型的输入是一个词汇,输出则是该词汇的上下文。如下图所示:

在这里插入图片描述

下面举一个例子,设”窗口“宽度为5,每次用”窗口“的第三个也就是中的词汇作为输入,其余上下文作为输出,分别构建数据集,如下图所示:

在这里插入图片描述

然后用构建好的数据集丢给词模型进行训练,如下图所示:

在这里插入图片描述

如果一个语料库稍微大一点,可能的结果就太多了,最后一层 SoftMax 的计算就会很耗时,有什么办法来解决吗?

下面提出了一个初始解决方案:假设,传统模型中,我们输入 not ,希望输出是 thou,但是由于语料库庞大,最后一层 SoftMax 太过耗时,所以我们可以改为:将 not 和 thou 同时作为输入,做一个二分类问题,类别 1 表示 not 和 thou 是邻居,类别 0 表示它们不是邻居。

在这里插入图片描述
上面提到的解决方案出发点非常好,但是由于训练集本来就是用上下文构建出来的,所以训练集构建出来的标签全为 1 ,无法较好的进行训练,如下图所示:

在这里插入图片描述
改进方案:加入一些负样本(负采样模型),一般负采样个数为 5 个就好,负采样示意图如下图所示:

在这里插入图片描述

4.3 CBOW 和 Skip-gram 对比

在这里插入图片描述


五、词向量训练过程

5.1 初始化词向量矩阵

在这里插入图片描述
在这里插入图片描述

5.2 训练模型

通过神经网络反向传播来计算更新,此时不光更新权重参数矩阵W,也会更新输入数据

在这里插入图片描述
训练完成后,我们就得到了比较准确的 Word Embeddings,从而得到了每个词的向量表示!!!


六、Python 代码实战

完整代码和数据集:基于PyTorch实现的词向量模型

6.1 Model

from torch import nn


class DNN(nn.Module):
    def __init__(self, vocabulary_size, embedding_dim):
        super(DNN, self).__init__()

        self.embedding = nn.Linear(vocabulary_size, embedding_dim, bias=False)
        print("embedding_size:", list(self.embedding.weight.size()))

        self.layers = nn.Sequential(
            nn.Linear(vocabulary_size * embedding_dim, embedding_dim // 2),
            nn.LeakyReLU(),
            nn.Linear(embedding_dim // 2, 4),
            nn.LeakyReLU(),
            nn.Linear(4, 1),
        )

        # Mean squared error loss
        self.criterion = nn.MSELoss()
        # self.criterion = nn.CrossEntropyLoss()

    def forward(self, x):
        x = self.embedding(x)
        x = x.view(x.size()[0], -1)
        x = self.layers(x)
        x = x.squeeze(1)
        return x

    def cal_loss(self, pred, target):
        """ Calculate loss """
        return self.criterion(pred, target)

6.2 DataSet

import random

import numpy as np
from torch.utils.data import Dataset


class MyDataSet(Dataset):
    def __init__(self, features, labels):
        self.features = features
        self.labels = labels

    def __getitem__(self, index):
        return self.features[index], self.labels[index]

    def __len__(self):
        return len(self.features)


def get_data_set(data_path, window_width, window_step, negative_sample_num):
    with open(data_path, 'r', encoding='utf-8') as file:
        document = file.read()
        document = document.replace(",", "").replace("?", "").replace(".", "").replace('"', '')
        data = document.split(" ")
        print(f"数据中共有 {len(data)} 个单词")

        # 构造词典
        vocabulary = set()
        for word in data:
            vocabulary.add(word)
        vocabulary = list(vocabulary)
        print(f"词典大小为 {len(vocabulary)}")

        # index_dict
        index_dict = dict()
        for index, word in enumerate(vocabulary):
            index_dict[word] = index

        # 开始滑动窗口,构造数据
        features = []
        labels = []
        neighbor_dict = dict()

        for start_index in range(0, len(data), window_step):
            if start_index + window_width - 1 < len(data):
                mid_index = int((start_index + start_index + window_width - 1) / 2)
                for index in range(start_index, start_index + window_width):
                    if index != mid_index:
                        feature = np.zeros((len(vocabulary), len(vocabulary)))
                        feature[index_dict[data[index]]][index_dict[data[index]]] = 1
                        feature[index_dict[data[mid_index]]][index_dict[data[mid_index]]] = 1
                        features.append(feature)
                        labels.append(1)
                        if data[mid_index] in neighbor_dict.keys():
                            neighbor_dict[data[mid_index]].add(data[index])
                        else:
                            neighbor_dict[data[mid_index]] = {data[index]}
        # 负采样
        for _ in range(negative_sample_num):
            random_word = vocabulary[random.randint(0, len(vocabulary))]
            for word in vocabulary:
                if random_word not in neighbor_dict.keys() or word not in neighbor_dict[random_word]:
                    feature = np.zeros((len(vocabulary), len(vocabulary)))
                    feature[index_dict[random_word]][index_dict[random_word]] = 1
                    feature[index_dict[word]][index_dict[word]] = 1
                    features.append(feature)
                    labels.append(0)
                    break
        # 返回dataset和词典
        return MyDataSet(features, labels), vocabulary, index_dict

6.3 Main

import random
from math import sqrt

import numpy as np
import torch
from torch.utils.data import DataLoader

from Python.机器学习.唐宇迪机器学习.词向量.DataSet import get_data_set
from Python.机器学习.唐宇迪机器学习.词向量.Model import DNN


def same_seed(seed):
    """
    Fixes random number generator seeds for reproducibility
    固定时间种子。由于cuDNN会自动从几种算法中寻找最适合当前配置的算法,为了使选择的算法固定,所以固定时间种子
    :param seed: 时间种子
    :return: None
    """
    torch.backends.cudnn.deterministic = True  # 解决算法本身的不确定性,设置为True 保证每次结果是一致的
    torch.backends.cudnn.benchmark = False  # 解决了算法选择的不确定性,方便复现,提升训练速度
    np.random.seed(seed)  # 按顺序产生固定的数组,如果使用相同的seed,则生成的随机数相同, 注意每次生成都要调用一次
    torch.manual_seed(seed)  # 手动设置torch的随机种子,使每次运行的随机数都一致
    random.seed(seed)
    if torch.cuda.is_available():
        # 为GPU设置唯一的时间种子
        torch.cuda.manual_seed(seed)
        torch.cuda.manual_seed_all(seed)


def train(model, train_loader, config):
    # Setup optimizer
    optimizer = getattr(torch.optim, config['optimizer'])(
        model.parameters(), **config['optim_hyper_paras'])

    device = config['device']
    epoch = 0
    while epoch < config['n_epochs']:
        model.train()  # set model to training mode
        loss_arr = []
        for x, y in train_loader:  # iterate through the dataloader
            optimizer.zero_grad()  # set gradient to zero
            x, y = x.to(device).to(torch.float32), y.to(device).to(torch.float32)  # move data to device (cpu/cuda)
            pred = model(x)  # forward pass (compute output)
            mse_loss = model.cal_loss(pred, y)  # compute loss
            mse_loss.backward()  # compute gradient (backpropagation)
            optimizer.step()  # update model with optimizer
            loss_arr.append(mse_loss.item())
        print(f"epoch: {epoch}/{config['n_epochs']} , loss: {np.mean(loss_arr)}")
        epoch += 1

    print('Finished training after {} epochs'.format(epoch))


def find_min_distance_word_vector(cur_i, vector, embeddings, vocabulary):
    def calc_distance(v1, v2):
        # 计算欧式距离
        distance = 0
        for i in range(len(v1)):
            distance += sqrt(pow(v1[i] - v2[i], 2))
        return distance

    min_distance = None
    min_i = -1
    for i, word in enumerate(vocabulary):
        if cur_i != i:
            distance = calc_distance(vector, embeddings[i].tolist())
            if min_distance is None or min_distance > distance:
                min_distance = distance
                min_i = i
    return min_i


if __name__ == '__main__':
    data_path = './data/data.txt'
    config = {
        'seed': 3407,  # Your seed number, you can pick your lucky number. :)
        'device': 'cuda' if torch.cuda.is_available() else 'cpu',
        'n_epochs': 20,  # Number of epochs.
        'batch_size': 64,
        'optimizer': 'Adam',
        'optim_hyper_paras': {  # hyper-parameters for the optimizer (depends on which optimizer you are using)
            'lr': 0.001,  # learning rate of optimizer
        },
        'embedding_dim': 6,  # 词向量长度
        'window_width': 5,  # 窗口的宽度
        'window_step': 2,  # 窗口滑动的步长
        'negative_sample_num': 10  # 要增加的负样本个数
    }

    same_seed(config['seed'])

    data_set, vocabulary, index_dict = get_data_set(data_path, config['window_width'], config['window_step'],
                                                    config['negative_sample_num'])
    train_loader = DataLoader(data_set, config['batch_size'], shuffle=True, drop_last=False, pin_memory=True)

    model = DNN(len(vocabulary), config['embedding_dim']).to(config['device'])

    train(model, train_loader, config)

    # 训练完,看看embeddings,展示部分词的词向量,并找到离它最近的词的词向量
    embeddings = torch.t(model.embedding.weight)
    for i in range(10):
        print('%-50s%s' % (f"{vocabulary[i]} 的词向量为 :", str(embeddings[i].tolist())))
        min_i = find_min_distance_word_vector(i, embeddings[i].tolist(), embeddings, vocabulary)
        print('%-45s%s' % (
            f"离 {vocabulary[i]} 最近的词为 {vocabulary[min_i]} , 它的词向量为 :", str(embeddings[min_i].tolist())))
        print('-' * 200)

6.4 运行输出

数据中共有 1803 个单词
词典大小为 511
embedding_size: [6, 511]
epoch: 0/20 , loss: 0.0752271132772429
epoch: 1/20 , loss: 0.01744390495137818
epoch: 2/20 , loss: 0.0030546926833554416
epoch: 3/20 , loss: 0.0025285633501449696
epoch: 4/20 , loss: 0.002311844104776371
epoch: 5/20 , loss: 0.002020565740071776
epoch: 6/20 , loss: 0.001762585903602405
epoch: 7/20 , loss: 0.0015661540336415719
epoch: 8/20 , loss: 0.0013828050599872846
epoch: 9/20 , loss: 0.0010562216170033104
epoch: 10/20 , loss: 0.0008050707044451867
epoch: 11/20 , loss: 0.0006666925565903575
epoch: 12/20 , loss: 0.0005228724374622592
epoch: 13/20 , loss: 0.00041554564311234953
epoch: 14/20 , loss: 0.0003863844721659884
epoch: 15/20 , loss: 0.00024095189464708056
epoch: 16/20 , loss: 0.0001828093964042254
epoch: 17/20 , loss: 0.0001404089290716863
epoch: 18/20 , loss: 0.00010190787191819701
epoch: 19/20 , loss: 6.971220871894714e-05
Finished training after 20 epochs
well 的词向量为 :                                      [0.2800050377845764, -0.28451332449913025, -0.288005530834198, -0.3119206130504608, 0.2786404490470886, 0.31298771500587463]
离 well 最近的词为 first , 它的词向量为 :                [0.11318866163492203, -0.1251109391450882, -0.13063986599445343, -0.11296737194061279, 0.1378508061170578, 0.13971801102161407]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
submitted 的词向量为 :                                 [0.15754808485507965, -0.12277694046497345, -0.14227379858493805, -0.14454570412635803, 0.05900704860687256, 0.09546193480491638]
离 submitted 最近的词为 benefit , 它的词向量为 :         [0.13462799787521362, -0.10862613469362259, -0.10275529325008392, -0.07748148590326309, 0.10121206194162369, 0.10051087290048599]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
even 的词向量为 :                                      [-0.11601416021585464, -0.10113148391246796, -0.1214226558804512, -0.10180512815713882, -0.09548257291316986, -0.11160479485988617]
离 even 最近的词为 working , 它的词向量为 :              [-0.1340179741382599, -0.10384820401668549, -0.1085871234536171, -0.09771087765693665, -0.09202782064676285, -0.11302905529737473]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
thus 的词向量为 :                                      [0.1400231420993805, 0.11062948405742645, -0.13136275112628937, -0.14278383553028107, 0.0380394384264946, 0.1342836171388626]
离 thus 最近的词为 problem , 它的词向量为 :              [0.13799253106117249, 0.12232215702533722, -0.11594908684492111, -0.14511127769947052, 0.11674903333187103, 0.14989981055259705]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
so 的词向量为 :                                        [-0.13579697906970978, -0.1544174700975418, -0.13814400136470795, 0.1473793238401413, -0.13407182693481445, -0.16138871014118195]
离 so 最近的词为 role , 它的词向量为 :                   [-0.13371147215366364, -0.1268460601568222, -0.12891902029514313, 0.10279709100723267, -0.11447536945343018, -0.14199912548065186]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
decisions 的词向量为 :                                 [-0.11366508901119232, 0.16771574318408966, 0.1678972989320755, -0.1269330531358719, -0.05488301441073418, 0.03212495520710945]
离 decisions 最近的词为 graduation , 它的词向量为 :      [-0.1385655254125595, 0.11743943393230438, 0.16122682392597198, -0.08773274719715118, -0.10684341937303543, -0.018613960593938828]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
retained 的词向量为 :                                  [0.1318095624446869, 0.1072487011551857, -0.09701842069625854, 0.12827205657958984, -0.07958601415157318, 0.12242742627859116]
离 retained 最近的词为 but , 它的词向量为 :              [0.12475789338350296, 0.10641714930534363, -0.10653595626354218, 0.10686526447534561, -0.11097636818885803, 0.12155742198228836]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
not 的词向量为 :                                       [0.11732926964759827, -0.1214861199259758, -0.12549108266830444, -0.14001798629760742, -0.11948511749505997, 0.10462098568677902]not 最近的词为 we , 它的词向量为 :                    [0.11353950947523117, -0.12036407738924026, -0.12329546362161636, -0.10175121575593948, -0.11156024783849716, 0.08613568544387817]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
agree 的词向量为 :                                     [0.1323355734348297, 0.07596761733293533, -0.1199847161769867, -0.07760312408208847, 0.12063225358724594, -0.12207814306020737]
离 agree 最近的词为 attitudes , 它的词向量为 :           [0.1297885924577713, 0.0682920590043068, -0.11543254554271698, -0.08852613717317581, 0.1026940643787384, -0.15329356491565704]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
our 的词向量为 :                                       [-0.005921764764934778, 0.13929229974746704, -0.12112995237112045, 0.11011514812707901, 0.10238232463598251, 0.11239470541477203]
离 our 最近的词为 iron-faced , 它的词向量为 :            [-0.11445378512144089, 0.12393463402986526, -0.12114288657903671, 0.11323738098144531, 0.1026541218161583, 0.11349711567163467]
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

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

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

相关文章

IDEA远程快速部署SpringBoot项目到Docker环境

1.LInux上先安装docker环境 https://blog.csdn.net/YXWik/article/details/128643662 2.配置Docker远程连接端口 1. vim /usr/lib/systemd/system/docker.service 2. 找到ExecStar 在后面添加 -H tcp://0.0.0.0:2375 3. 退出编辑界面&#xff1a;先按esc&#xff0c;然后"…

【JAVA程序设计】(C00100)基于Springboot+html的前后端分离停车场管理系统

基于Springboothtml的前后端分离停车场管理系统项目简介项目获取开发环境项目技术运行截图项目简介 基于SpringBoothtml的前后端分离的停车场管理系统&#xff0c;本系统分为二种角色&#xff1a;管理员和收银员。 1&#xff0e;登录&#xff1a;管理员可以通过系统分配的账号…

Android 系统框架结构

目录 1.应用层(System Apps)&#xff1a; 2.应用框架层(Java API Framework)&#xff1a; 3.系统运行库层(Native)&#xff1a; 4.硬件抽象层(HAL)&#xff1a; 5.Linux内核层&#xff08;Linux Kernel&#xff09;&#xff1a; 大部分开发的同学是不太清楚Android的系统的…

解决企业微信启动报错:0x0000142无法打开

解决企业微信启动报错&#xff1a;0x0000142无法打开1.问题描述2.问题查找3.问题解决4.事后感悟系统&#xff1a;Win10 WXWork&#xff1a;4.0.20.6020 1.问题描述 不知道从啥时候开始&#xff0c;打开企业微信会报错&#xff08;见下图&#xff09;&#xff0c;报错代码是&am…

【Redis】缓存穿透问题及其解决方案

【Redis】缓存穿透问题及其解决方案 文章目录【Redis】缓存穿透问题及其解决方案1. 缓存穿透概念及原因2. 解决方案2.1 缓存空对象2.1.1 缓存空对象的优缺点2.1.2 改进代码2.2 布隆过滤2.2.1 布隆过滤的优缺点1. 缓存穿透概念及原因 缓存穿透&#xff1a;客户端请求的数据在 缓…

HTML与CSS基础(十)—— 综合项目

应用前面技术知识 完成小兔鲜儿项目设计图素材下载&#xff1a;链接: https://pan.baidu.com/s/1o5mWkgEfaTAA5spxMLuXEQ?pwdex7e 提取码: ex7e 一、Header 部分开发 布局分析&#xff1a;header布局分析&#xff1a;xtx-shortcut ①布局分析&#xff1a;xtx-shortcut ②布局分…

Hudi系列3:Hudi核心概念

文章目录Hudi架构一. 时间轴(TimeLine)1.1 时间轴(TimeLine)概念1.2 Hudi的时间线由组成1.3 时间线上的Instant action操作类型1.4 时间线上State状态类型1.5 时间线官网实例二. 文件布局三. 索引3.1 简介3.2 对比Hive没有索引的区别3.3 Hudi索引类型3.4 全局索引与非全局索引四…

数学建模-回归分析(Stata)

注意&#xff1a;代码文件仅供参考&#xff0c;一定不要直接用于自己的数模论文中国赛对于论文的查重要求非常严格&#xff0c;代码雷同也算作抄袭 如何修改代码避免查重的方法&#xff1a;https://www.bilibili.com/video/av59423231 //清风数学建模 一、基础知识 1.简介 …

不得不面对的随机MAC问题

一、现状 为了完善安全机制、保护用户隐私&#xff0c;各个设备厂商开发了 MAC 地址随机功能&#xff0c;防止用户信息泄露。随机 MAC 地址&#xff0c;就是一个随机生成的伪 MAC 地址&#xff0c;一个假 MAC 地址&#xff0c;使用随机 MAC 地址进行网络通信&#xff0c;而不是…

全网圣诞树最全完整源码下载合集【可下载】

文章目录一、全部源码打包下载&#xff1a;二、效果预览001-html版本 豪华动态圣诞树 抖音同款002-圣诞树灯光跟随音乐节拍一起呼吸点亮下雪动画效果代码003-圣诞树彩带飘动节日快乐效果代码004-圣诞树带音乐旋转拉伸动画效果005-python版本python取消延迟秒出图版 【全网最强无…

当FutureTask遇上DiscardPolicy,有坑

文章目录有啥坑呢&#xff1f;知识回顾问题触发条件问题复现问题分析问题修复扩展哈喽&#xff0c;你好&#xff0c;我是余数。今天来了解下当 FutureTask 遇上 DiscardPolicy 或 DiscardOldestPolicy 时容易掉的坑&#xff0c;然后分析分析问题产生的原因以及如何规避这类问题…

LVS+Keepalived+Nginx具体配置步骤

视频链接&#xff1a;4-6 搭建LVS-DR模式- 为两台RS配置虚拟IP_哔哩哔哩_bilibili 视频笔记链接&#xff1a;笔记 一、服务器与Ip约定 LVS DIP: 192.168.1.151 VIP: 192.168.1.150 Nginx1 RIP: 192.168.1.171 VIP: 192.168.1.150 Nginx2 RIP: 192.168.1.172 VIP: 192.168…

力扣 2283. 判断一个数的数字计数是否等于数位的值

题目 给你一个下标从 0 开始长度为 n 的字符串 num &#xff0c;它只包含数字。 如果对于 每个 0 < i < n 的下标 i &#xff0c;都满足数位 i 在 num 中出现了 num[i]次&#xff0c;那么请你返回 true &#xff0c;否则返回 false 。 示例 输入&#xff1a;num “1…

vue文件上传

vue文件上传 前言 今天写一篇关于文件上传的文章&#xff0c;其实对于真正工作的人来说&#xff0c;这不是很难的事&#xff0c;但对于新手来说无疑是个新技术 实现功能如下图 根据上传文件类型显示对应文件类型&#xff0c;图片直接显示&#xff0c;当然图片特可以做对应类型…

【NI Multisim 14.0原理图设计基础——参数属性设置】

目录 序言 &#x1f46c;一、参数属性设置 序言 NI Multisim最突出的特点之一就是用户界面友好。它可以使电路设计者方便、快捷地使用虚拟元器件和仪器、仪表进行电路设计和仿真。 首先启动NI Multisim 14.0&#xff0c;打开如图所示的启动界面&#xff0c;完成初始化后&…

初始C语言-分支与循环语句

目录 一、语句 1. 什么是语句&#xff1f; C语句可分为以下五类&#xff1a; 1. 表达式语句 2. 函数调用语句 3. 控制语句 4. 复合语句 5. 空语句 2. 控制语句&#xff1a; 1. 条件判断语句也叫分支语句&#xff1a;if语句、switch语句&#xff1b; 2. 循环执行语句…

extern “C“的作用以及c/c++代码互调

一、目的相信从事嵌入开发的小伙伴肯定遇到过使用第三库的情景&#xff0c;有时候可能是C中调用C库&#xff0c;有时候可能又是C中调用C库&#xff1b;如果你遇到过&#xff0c;那你肯定知道extern "C"的作用.本篇的目的就是给大家介绍C/C互相调用的原理和实践。二、…

RK3588平台开发系列讲解(内核调试篇)CPU Hotplug 调试

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、CPU Hotplug 介绍二、CPU Hotplug 内核开关三、sysfs调试沉淀、分享、成长,让自己和他人都能有所收获!😄 📢多核系统底层驱动提供了cpu的Plugin/Unplug接口,可以实现动态调整cpu使用运行。 一、CPU Hotplu…

在 Node JS 中实现微服务架构

&#x1f4cd;简介&#x1f642; 正如我们在之前的博客“单体与微服务&#xff1a;一种实用方法”中讨论的那样。但是今天我们要在 NodeJS 中实现微服务架构。&#x1f449; 您可以使用任何技术&#xff0c;如 Spring、Python 等。但我们将使用 NodeJS 进行演示。&#x1f4cd;…

PostgreSQL下载、安装和配置使用

1&#xff09;下载 PostgreSQL官网下载&#xff1a;https://www.enterprisedb.com/downloads/postgres-postgresql-downloads 2&#xff09;安装 双击运行安装包 选择安装目录&#xff0c;不推荐安装在C盘。 选择需要安装的服务&#xff0c;不明白是啥的全选就行&#xf…