C2W4.LAB.Word_Embedding.Part2

news2024/12/23 14:22:11

理论课:C2W4.Word Embeddings with Neural Networks

文章目录


理论课: C2W4.Word Embeddings with Neural Networks

Training the CBOW model

先根据网络构架搞清楚输出、隐藏层、输出维度
在这里插入图片描述
图中描述的是一个简单的神经网络模型,通常用于处理词嵌入(Word Embedding)任务,如连续词袋模型(Continuous Bag of Words, CBOW)。这个模型由输入层、隐藏层和输出层组成。下面是每个层和相关操作的维度解释:

  1. 输入层 (Input layer):

    • 维度: ( N × V ) (N \times V) (N×V)
    • 描述:输入层接收一个词的one-hot编码,其中(N)是词汇表的大小, ( V ) (V) (V)是词汇表中每个词的向量维度(即one-hot编码的长度)。
  2. 权重矩阵 W1 (Weight matrix W1):

    • 维度: ( N × V ) (N \times V) (N×V)到$ ( N × 1 ) (N \times 1) (N×1)
    • 描述:这是从输入层到隐藏层的权重矩阵。每个词的one-hot编码通过这个权重矩阵转换为隐藏层的激活值。
  3. 偏置向量 b1 (Bias vector b1):

    • 维度: ( N × 1 ) (N \times 1) (N×1)
    • 描述:这是加在隐藏层激活值上的偏置项。
  4. 隐藏层 (Hidden layer):

    • 维度: ( N × 1 ) (N \times 1) (N×1)
    • 描述:隐藏层的激活值由输入层的加权和加上偏置后通过激活函数(如ReLU)计算得到。
  5. 激活函数 ReLU (Activation function ReLU):

    • 描述:隐藏层的激活函数,通常用于引入非线性,帮助模型学习复杂的模式。
  6. 权重矩阵 W2 (Weight matrix W2):

    • 维度: ( V × N ) (V \times N) (V×N)
    • 描述:这是从隐藏层到输出层的权重矩阵。它将隐藏层的激活值转换为输出层的预测值。
  7. 偏置向量 b2 (Bias vector b2):

    • 维度: ( V × 1 ) (V \times 1) (V×1)
    • 描述:这是加在输出层预测值上的偏置项。
  8. 输出层 (Output layer):

    • 维度: ( V × 1 ) (V \times 1) (V×1)
    • 描述:输出层的值是模型对每个词的预测概率,通常通过softmax函数转换为概率分布。
  9. softmax 函数:

    • 描述:softmax函数用于将输出层的线性预测值转换为概率分布,使得所有输出概率的和为1。
  10. 预测值 y ^ \hat{y} y^ (Predicted value y ^ \hat{y} y^):

    • 描述:模型的最终输出,表示为每个词的概率。

这里将 N N N 设为 3。 N N N是 CBOW 模型的一个超参数,代表单词嵌入向量的大小以及隐藏层的大小。
V V V这里为5,是词表大小。

# Define the size of the word embedding vectors and save it in the variable 'N'
N = 3

# Define V. Remember this was the size of the vocabulary in the previous lecture notebooks
V = 5

Forward propagation

Initialization of the weights and biases

在开始训练CBOW 之前,需要用随机值初始化权重矩阵和偏置向量。正常是需要使用numpy.random.rand来完成该操作,这里直接填充好(大家实验结果才会一致,也可以用随机种子完成):

# Define first matrix of weights
W1 = np.array([[ 0.41687358,  0.08854191, -0.23495225,  0.28320538,  0.41800106],
               [ 0.32735501,  0.22795148, -0.23951958,  0.4117634 , -0.23924344],
               [ 0.26637602, -0.23846886, -0.37770863, -0.11399446,  0.34008124]])

# Define second matrix of weights
W2 = np.array([[-0.22182064, -0.43008631,  0.13310965],
               [ 0.08476603,  0.08123194,  0.1772054 ],
               [ 0.1871551 , -0.06107263, -0.1790735 ],
               [ 0.07055222, -0.02015138,  0.36107434],
               [ 0.33480474, -0.39423389, -0.43959196]])

# Define first vector of biases
b1 = np.array([[ 0.09688219],
               [ 0.29239497],
               [-0.27364426]])

# Define second vector of biases
b2 = np.array([[ 0.0352008 ],
               [-0.36393384],
               [-0.12775555],
               [-0.34802326],
               [-0.07017815]])

检查参数的维度:

print(f'V (vocabulary size): {V}')
print(f'N (embedding size / size of the hidden layer): {N}')
print(f'size of W1: {W1.shape} (NxV)')
print(f'size of b1: {b1.shape} (Nx1)')
print(f'size of W2: {W2.shape} (VxN)')
print(f'size of b2: {b2.shape} (Vx1)')

结果:
V (vocabulary size): 5
N (embedding size / size of the hidden layer): 3
size of W1: (3, 5) (NxV)
size of b1: (3, 1) (Nx1)
size of W2: (5, 3) (VxN)
size of b2: (5, 1) (Vx1)
然后使用Part1中创建的一系列函数完成相关数据预处理操作:

# Define the tokenized version of the corpus
words = ['i', 'am', 'happy', 'because', 'i', 'am', 'learning']

# Get 'word2Ind' and 'Ind2word' dictionaries for the tokenized corpus
word2Ind, Ind2word = get_dict(words)

# Define the 'get_windows' function as seen in a previous notebook
def get_windows(words, C):
    i = C
    while i < len(words) - C:
        center_word = words[i]
        context_words = words[(i - C):i] + words[(i+1):(i+C+1)]
        yield context_words, center_word
        i += 1

# Define the 'word_to_one_hot_vector' function as seen in a previous notebook
def word_to_one_hot_vector(word, word2Ind, V):
    one_hot_vector = np.zeros(V)
    one_hot_vector[word2Ind[word]] = 1
    return one_hot_vector

# Define the 'context_words_to_vector' function as seen in a previous notebook
def context_words_to_vector(context_words, word2Ind, V):
    context_words_vectors = [word_to_one_hot_vector(w, word2Ind, V) for w in context_words]
    context_words_vectors = np.mean(context_words_vectors, axis=0)
    return context_words_vectors

# Define the generator function 'get_training_example' as seen in a previous notebook
def get_training_example(words, C, word2Ind, V):
    for context_words, center_word in get_windows(words, C):
        yield context_words_to_vector(context_words, word2Ind, V), word_to_one_hot_vector(center_word, word2Ind, V)

Training example

# Save generator object in the 'training_examples' variable with the desired arguments
training_examples = get_training_example(words, 2, word2Ind, V)

使用 yield 关键字的 get_training_examples 被称为生成器。运行时,它会生成一个迭代器(iterator),迭代器是一种特殊类型的对象…你可以对它进行迭代(例如使用 for 循环),以检索函数生成的连续值。
在这种情况下,get_training_examples会生成训练示例,对training_examples进行迭代会返回连续的训练示例。
下面取出生成器的第一个值:

# Get first values from generator
x_array, y_array = next(training_examples)

next 是另一个特殊的关键字,用于从迭代器中获取下一个可用值。上面的代码你会得到第一个值,也就是第一个训练示例。如果再次运行这个单元,就会得到下一个值,依此类推,直到迭代器返回的值用完为止。
这里使用 next 是因为只进行一次迭代训练,如果在多个迭代中进行完整的训练,需要使用常规的 for 循环以提供训练示例的迭代器。

打印提取到的向量:

# Print context words vector
x_array

结果:array([0.25, 0.25, 0. , 0.5 , 0. ])

# Print one hot vector of center word
y_array

结果:array([0., 0., 1., 0., 0.])
现在将这些向量转换为矩阵(或二维数组),以便能够在正确类型的对象上执行矩阵乘法

# Copy vector
x = x_array.copy()

# Reshape it
x.shape = (V, 1)

# Print it
print(f'x:\n{x}\n')

# Copy vector
y = y_array.copy()

# Reshape it
y.shape = (V, 1)

# Print it
print(f'y:\n{y}')

结果:

x:
[[0.25]
 [0.25]
 [0.  ]
 [0.5 ]
 [0.  ]]

y:
[[0.]
 [0.]
 [1.]
 [0.]
 [0.]]

定义激活函数:

# Define the 'relu' function as seen in the previous lecture notebook
def relu(z):
    result = z.copy()
    result[result < 0] = 0
    return result

# Define the 'softmax' function as seen in the previous lecture notebook
def softmax(z):
    e_z = np.exp(z)
    sum_e_z = np.sum(e_z)
    return e_z / sum_e_z

Values of the hidden layer

初始化完毕前向传播所需的所有变量,可以使用下面的公式计算隐藏层的值:
z 1 = W 1 x + b 1 h = R e L U ( z 1 ) \begin{align} \mathbf{z_1} = \mathbf{W_1}\mathbf{x} + \mathbf{b_1} \tag{1} \\ \mathbf{h} = \mathrm{ReLU}(\mathbf{z_1}) \tag{2} \\ \end{align} z1=W1x+b1h=ReLU(z1)(1)(2)
根据公式1写代码:

# Compute z1 (values of first hidden layer before applying the ReLU function)
z1 = np.dot(W1, x) + b1
# Print z1
z1

结果:

array([[ 0.36483875],
       [ 0.63710329],
       [-0.3236647 ]])

根据公式2写代码:

# Compute h (z1 after applying ReLU function)
h = relu(z1)

# Print h
h

结果:

array([[0.36483875],
       [0.63710329],
       [0.        ]])

注意观察,上面是ReLU的结果。

Values of the output layer

以下是计算输出层(以向量 y ^ \hat{y} y^表示)值所需的公式:
z 2 = W 2 h + b 2 y ^ = s o f t m a x ( z 2 ) \begin{align} \mathbf{z_2} &= \mathbf{W_2}\mathbf{h} + \mathbf{b_2} \tag{3} \\ \mathbf{\hat y} &= \mathrm{softmax}(\mathbf{z_2}) \tag{4} \\ \end{align} z2y^=W2h+b2=softmax(z2)(3)(4)
根据公式3写代码:

# Compute z2 (values of the output layer before applying the softmax function)
z2 = np.dot(W2, h) + b2

# Print z2
z2

结果:

array([[-0.31973737],
       [-0.28125477],
       [-0.09838369],
       [-0.33512159],
       [-0.19919612]])

注意其维度是: ( V × 1 ) (V \times 1) (V×1)
根据公式4计算输出:

# Compute y_hat (z2 after applying softmax function)
y_hat = softmax(z2)

# Print y_hat
y_hat

结果:

array([[0.18519074],
       [0.19245626],
       [0.23107446],
       [0.18236353],
       [0.20891502]])

思考:得到了输出 y ^ \hat{y} y^,如何计算其预测的单词 1

Cross-entropy loss

有了预测结果,就可以计算Cross-entropy损失来决定预测的准确度有多少。
这里因为只有一个训练样本,而非一个batch的训练样本,因此用lost,不是cost。当然,cost是lost的一般形式。
再次打印预测结果和真实值:

# Print prediction
y_hat

结果:

array([[0.18519074],
       [0.19245626],
       [0.23107446],
       [0.18236353],
       [0.20891502]])
# Print target value
y

结果:

array([[0.],
       [0.],
       [1.],
       [0.],
       [0.]])

交叉熵损失计算公式为:

J = − ∑ k = 1 V y k log ⁡ y ^ k (6) J=-\sum\limits_{k=1}^{V}y_k\log{\hat{y}_k} \tag{6} J=k=1Vyklogy^k(6)
对应的代码为:

def cross_entropy_loss(y_predicted, y_actual):
    # Fill the loss variable with your code
    loss = np.sum(-np.log(y_hat)*y)
    return loss

测试:

# Print value of cross entropy loss for prediction and target value
cross_entropy_loss(y_hat, y)

结果:1.4650152923611106
这个结果不好也不坏,模型还没学习到任何信息,需要继续进行反向传播

Backpropagation

根据网络构架,反向传播用到的公式为:
∂ J ∂ W 1 = R e L U ( W 2 ⊤ ( y ^ − y ) ) x ⊤ ∂ J ∂ W 2 = ( y ^ − y ) h ⊤ ∂ J ∂ b 1 = R e L U ( W 2 ⊤ ( y ^ − y ) ) ∂ J ∂ b 2 = y ^ − y \begin{align} \frac{\partial J}{\partial \mathbf{W_1}} &= \rm{ReLU}\left ( \mathbf{W_2^\top} (\mathbf{\hat{y}} - \mathbf{y})\right )\mathbf{x}^\top \tag{7}\\ \frac{\partial J}{\partial \mathbf{W_2}} &= (\mathbf{\hat{y}} - \mathbf{y})\mathbf{h^\top} \tag{8}\\ \frac{\partial J}{\partial \mathbf{b_1}} &= \rm{ReLU}\left ( \mathbf{W_2^\top} (\mathbf{\hat{y}} - \mathbf{y})\right ) \tag{9}\\ \frac{\partial J}{\partial \mathbf{b_2}} &= \mathbf{\hat{y}} - \mathbf{y} \tag{10} \end{align} W1JW2Jb1Jb2J=ReLU(W2(y^y))x=(y^y)h=ReLU(W2(y^y))=y^y(7)(8)(9)(10)
以上公式是针对单个样本的,batch操作会更复杂,先计算公式10

# Compute vector with partial derivatives of loss function with respect to b2
grad_b2 = y_hat - y

# Print this vector
grad_b2

结果:

array([[ 0.18519074],
       [ 0.19245626],
       [-0.76892554],
       [ 0.18236353],
       [ 0.20891502]])

然后根据公式8写代码:

# Compute matrix with partial derivatives of loss function with respect to W2
grad_W2 = np.dot(y_hat - y, h.T)

# Print matrix
grad_W2

结果:

array([[ 0.06756476,  0.11798563,  0.        ],
       [ 0.0702155 ,  0.12261452,  0.        ],
       [-0.28053384, -0.48988499, -0.        ],
       [ 0.06653328,  0.1161844 ,  0.        ],
       [ 0.07622029,  0.13310045,  0.        ]])

按公式9写代码:

# Compute vector with partial derivatives of loss function with respect to b1
grad_b1 = relu(np.dot(W2.T, y_hat - y))

# Print vector
grad_b1

结果:

array([[0.        ],
       [0.        ],
       [0.17045858]])

最后计算公式7:

# Compute matrix with partial derivatives of loss function with respect to W1
grad_W1 = np.dot(relu(np.dot(W2.T, y_hat - y)), x.T)

# Print matrix
grad_W1

结果:

array([[0.        , 0.        , 0.        , 0.        , 0.        ],
       [0.        , 0.        , 0.        , 0.        , 0.        ],
       [0.04261464, 0.04261464, 0.        , 0.08522929, 0.        ]])

再次确认结果的维度:

print(f'V (vocabulary size): {V}')
print(f'N (embedding size / size of the hidden layer): {N}')
print(f'size of grad_W1: {grad_W1.shape} (NxV)')
print(f'size of grad_b1: {grad_b1.shape} (Nx1)')
print(f'size of grad_W2: {grad_W2.shape} (VxN)')
print(f'size of grad_b2: {grad_b2.shape} (Vx1)')

结果:
V (vocabulary size): 5
N (embedding size / size of the hidden layer): 3
size of grad_W1: (3, 5) (NxV)
size of grad_b1: (3, 1) (Nx1)
size of grad_W2: (5, 3) (VxN)
size of grad_b2: (5, 1) (Vx1)

Gradient descent

在梯度下降阶段,可使用下面的公式从原始矩阵和向量中减去 α \alpha α 乘以梯度来更新权重和偏置。
W 1 : = W 1 − α ∂ J ∂ W 1 W 2 : = W 2 − α ∂ J ∂ W 2 b 1 : = b 1 − α ∂ J ∂ b 1 b 2 : = b 2 − α ∂ J ∂ b 2 \begin{align} \mathbf{W_1} &:= \mathbf{W_1} - \alpha \frac{\partial J}{\partial \mathbf{W_1}} \tag{11}\\ \mathbf{W_2} &:= \mathbf{W_2} - \alpha \frac{\partial J}{\partial \mathbf{W_2}} \tag{12}\\ \mathbf{b_1} &:= \mathbf{b_1} - \alpha \frac{\partial J}{\partial \mathbf{b_1}} \tag{13}\\ \mathbf{b_2} &:= \mathbf{b_2} - \alpha \frac{\partial J}{\partial \mathbf{b_2}} \tag{14}\\ \end{align} W1W2b1b2:=W1αW1J:=W2αW2J:=b1αb1J:=b2αb2J(11)(12)(13)(14)
先给超参数一个初始值:

# Define alpha
alpha = 0.03

先按公式11计算:

# Compute updated W1
W1_new = W1 - alpha * grad_W1

比较更新前后的值:

print('old value of W1:')
print(W1)
print()
print('new value of W1:')
print(W1_new)

结果:

old value of W1:
[[ 0.41687358  0.08854191 -0.23495225  0.28320538  0.41800106]
 [ 0.32735501  0.22795148 -0.23951958  0.4117634  -0.23924344]
 [ 0.26637602 -0.23846886 -0.37770863 -0.11399446  0.34008124]]

new value of W1:
[[ 0.41687358  0.08854191 -0.23495225  0.28320538  0.41800106]
 [ 0.32735501  0.22795148 -0.23951958  0.4117634  -0.23924344]
 [ 0.26509758 -0.2397473  -0.37770863 -0.11655134  0.34008124]]

根据公式12.13.14更新其他三个参数:

# Compute updated W2
W2_new = W2 - alpha * grad_W2

# Compute updated b1
b1_new = b1 - alpha * grad_b1

# Compute updated b2
b2_new = b2 - alpha * grad_b2


print('W2_new')
print(W2_new)
print()
print('b1_new')
print(b1_new)
print()
print('b2_new')
print(b2_new)

结果:

W2_new
[[-0.22384758 -0.43362588  0.13310965]
 [ 0.08265956  0.0775535   0.1772054 ]
 [ 0.19557112 -0.04637608 -0.1790735 ]
 [ 0.06855622 -0.02363691  0.36107434]
 [ 0.33251813 -0.3982269  -0.43959196]]

b1_new
[[ 0.09688219]
 [ 0.29239497]
 [-0.27875802]]

b2_new
[[ 0.02964508]
 [-0.36970753]
 [-0.10468778]
 [-0.35349417]
 [-0.0764456 ]]

Extracting word embedding vectors

开始前,把CBOW训练好的参数都重新给一次:

import numpy as np
from utils2 import get_dict

# Define the tokenized version of the corpus
words = ['i', 'am', 'happy', 'because', 'i', 'am', 'learning']

# Define V. Remember this is the size of the vocabulary
V = 5

# Get 'word2Ind' and 'Ind2word' dictionaries for the tokenized corpus
word2Ind, Ind2word = get_dict(words)


# Define first matrix of weights
W1 = np.array([[ 0.41687358,  0.08854191, -0.23495225,  0.28320538,  0.41800106],
               [ 0.32735501,  0.22795148, -0.23951958,  0.4117634 , -0.23924344],
               [ 0.26637602, -0.23846886, -0.37770863, -0.11399446,  0.34008124]])

# Define second matrix of weights
W2 = np.array([[-0.22182064, -0.43008631,  0.13310965],
               [ 0.08476603,  0.08123194,  0.1772054 ],
               [ 0.1871551 , -0.06107263, -0.1790735 ],
               [ 0.07055222, -0.02015138,  0.36107434],
               [ 0.33480474, -0.39423389, -0.43959196]])

# Define first vector of biases
b1 = np.array([[ 0.09688219],
               [ 0.29239497],
               [-0.27364426]])

# Define second vector of biases
b2 = np.array([[ 0.0352008 ],
               [-0.36393384],
               [-0.12775555],
               [-0.34802326],
               [-0.07017815]])

一共有三种提取词向量的方式。

Option 1: extract embedding vectors from W 1 \mathbf{W_1} W1

观察参数 W 1 \mathbf{W_1} W1,这个矩阵的第一列(3个元素)对应第一个单词的表征,第二列对应第二个单词,以此类推。我们把词库里面的单词按index打印出来:

# Print corresponding word for each index within vocabulary's range
for i in range(V):
    print(Ind2word[i])

结果:
am
because
happy
i
learning
将参数 W 1 \mathbf{W_1} W1对应单词的表征提取出来:

# Loop through each word of the vocabulary
for word in word2Ind:
    # Extract the column corresponding to the index of the word in the vocabulary
    word_embedding_vector = W1[:, word2Ind[word]]
    # Print word alongside word embedding vector
    print(f'{word}: {word_embedding_vector}')

结果:
am: [0.41687358 0.32735501 0.26637602]
because: [ 0.08854191 0.22795148 -0.23846886]
happy: [-0.23495225 -0.23951958 -0.37770863]
i: [ 0.28320538 0.4117634 -0.11399446]
learning: [ 0.41800106 -0.23924344 0.34008124]

Option 2: extract embedding vectors from W 2 \mathbf{W_2} W2

第二个选择是使用 W 2 \mathbf{W_2} W2的转置来提取单词的表征,先看 W 2 \mathbf{W_2} W2的转置:

# Print transposed W2
W2.T

结果:

array([[-0.22182064,  0.08476603,  0.1871551 ,  0.07055222,  0.33480474],
       [-0.43008631,  0.08123194, -0.06107263, -0.02015138, -0.39423389],
       [ 0.13310965,  0.1772054 , -0.1790735 ,  0.36107434, -0.43959196]])

将单词和其表征打印出来:

# Loop through each word of the vocabulary
for word in word2Ind:
    # Extract the column corresponding to the index of the word in the vocabulary
    word_embedding_vector = W2.T[:, word2Ind[word]]
    # Print word alongside word embedding vector
    print(f'{word}: {word_embedding_vector}')

结果:

am: [-0.22182064 -0.43008631  0.13310965]
because: [0.08476603 0.08123194 0.1772054 ]
happy: [ 0.1871551  -0.06107263 -0.1790735 ]
i: [ 0.07055222 -0.02015138  0.36107434]
learning: [ 0.33480474 -0.39423389 -0.43959196]

Option 3: extract embedding vectors from W 1 \mathbf{W_1} W1 and W 2 \mathbf{W_2} W2

将前面两种方法结合到一起,计算 W 1 \mathbf{W_1} W1 W 2 ⊤ \mathbf{W_2^\top} W2的平均,得到W3

# Compute W3 as the average of W1 and W2 transposed
W3 = (W1+W2.T)/2

# Print W3
W3

结果:

array([[ 0.09752647,  0.08665397, -0.02389858,  0.1768788 ,  0.3764029 ],
       [-0.05136565,  0.15459171, -0.15029611,  0.19580601, -0.31673866],
       [ 0.19974284, -0.03063173, -0.27839106,  0.12353994, -0.04975536]])

打印单词表征结果:

# Loop through each word of the vocabulary
for word in word2Ind:
    # Extract the column corresponding to the index of the word in the vocabulary
    word_embedding_vector = W3[:, word2Ind[word]]
    # Print word alongside word embedding vector
    print(f'{word}: {word_embedding_vector}')

结果:

am: [ 0.09752647 -0.05136565  0.19974284]
because: [ 0.08665397  0.15459171 -0.03063173]
happy: [-0.02389858 -0.15029611 -0.27839106]
i: [0.1768788  0.19580601 0.12353994]
learning: [ 0.3764029  -0.31673866 -0.04975536]

  1. 可以看输出向量 y ^ \hat{y} y^中那个维度最大,对应的索引号的单词就是预测结果。可以执行:print(Ind2word[np.argmax(y_hat)]) ↩︎

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

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

相关文章

121页PPT | 集团股份有限公司IT信息化规划报告

这份PPT是集团股份有限公司的IT信息化规划报告&#xff0c;全面涵盖了公司在信息化建设方面的需求分析、规划实施、投资概算以及建议方案&#xff0c;通过现代化信息技术提升企业的管理效率和市场竞争力。 该资料可编辑PPT格式&#xff0c;本文重点展现PPT整体逻辑&#xff0c…

[项目详解][boost搜索引擎#2] 建立index | 安装分词工具cppjieba | 实现倒排索引

目录 编写建立索引的模块 Index 1. 设计节点 2.基本结构 3.(难点) 构建索引 1. 构建正排索引&#xff08;BuildForwardIndex&#xff09; 2.❗构建倒排索引 3.1 cppjieba分词工具的安装和使用 3.2 引入cppjieba到项目中 倒排索引代码 本篇文章&#xff0c;我们将继续项…

虚拟机安装麒麟v10、配置网络、安装docker

一、虚拟机安装麒麟v10 1、下载iso&#xff08;https://www.kylinos.cn/support/trial.html&#xff09; 2、虚拟机安装 3、选择 4、设置开机自动连接网络 参考地址&#xff1a;https://www.cnblogs.com/goding/p/18283912 安装好后发现屏幕分辨率毕竟低&#xff0c;点设置分…

龙蟠科技业绩压力显著:资产负债率持续攀升,产能利用率也不乐观

《港湾商业观察》施子夫 黄懿 去年十月至今两度递表后&#xff0c;10月17日&#xff0c;江苏龙蟠科技股份有限公司(以下简称&#xff0c;龙蟠科技&#xff1b;603906.SH&#xff0c;02465.HK)通过港交所主板上市聆讯。 很快&#xff0c;龙蟠科技发布公告称&#xff0c;公司全…

缓存池(对象池)使用

框架介绍 对象池的实现是为了优化内存管理和提升性能&#xff0c;尤其是在创建和销毁大量对象时&#xff0c;通过复用已经创建的对象来减少垃圾回收的负担。 实现概述 开放公共方法 记忆已更新 这个对象池的实现是为了优化内存管理和提升性能&#xff0c;尤其是在创建和销…

【Spring】详解SpringMVC,一篇文章带你快速入门

目录 一、初始MVC 二、SpringMVC 三、Spring MVC的运用 ⭕RequestMapping ⭕传递参数 1、传递单个参数 2、传递多个参数 3、参数重命名 4、传递数组与集合 5、获取路径参数 6、传递JSON数据 7、上传文件 一、初始MVC MVC&#xff08;Model-View-Controller&#…

python 深度学习 项目调试 识别数学公式 LaTeX-OCR

起因&#xff0c; 目的: 提取图片中的数学公式。 其实这个项目&#xff0c;我很久之前就做过。 而且,我还录了一个视频: https://www.bilibili.com/video/BV1nD421p7jS/?vd_source198e876d811b3ccea94908fd163c223f 简介: 项目来源: https://github.com/lukas-blecher/La…

MongoDB简单学习

MongoDB 一、基本使用 1.1业务应用场景 传统的关系型数据库&#xff08;如Mysql&#xff09;&#xff0c;在数据库操作的“三高”需求以及对应web2.0的网站需求面前&#xff0c;显得力不从心 三高&#xff1a; High performance - 对数据库高并发读写的要求Huge Storage -…

STM32--基于STM32F103C8T6的OV7670摄像头显示

本文介绍基于STM32F103C8T6实现的OV7670摄像头显示设计&#xff08;完整资源及代码见文末链接&#xff09; 一、简介 本文实现的功能&#xff1a;基于STM32F103C8T6实现的OV7670摄像头模组实时在2.2寸TFT彩屏上显示出来 所需硬件&#xff1a; STM32F103C8T6最小系统板、OV76…

[C++ 11] 列表初始化:轻量级对象initializer_list

C发展历史 C11是C语言的第二个主要版本&#xff0c;也是自C98以来最重要的一次更新。它引入了大量的新特性&#xff0c;标准化了已有的实践&#xff0c;并极大地改进了C程序员可用的抽象能力。在2011年8月12日被ISO正式采纳之前&#xff0c;人们一直使用“C0x”这个名称&#…

10-1.idea中的项目结构,辅助快捷键,模块的操作

idea中的项目结构和辅助快捷键 IDEA中项目结构 首先是创建项目&#xff0c;新建的项目中有子项目&#xff0c;我们可以创建模块 然后在模块中我们可以创建包&#xff0c;在包中的SRC中写我们的源代码&#xff0c;也就是类。 VScode写Java项目 如何你电脑比较卡的话&#…

基于GPT的智能客服落地实践

&#x1f4cd;前言 在日常生活中&#xff0c;「客服」这个角色几乎贯穿着我们生活的方方面面。比如&#xff0c;淘宝买东西时&#xff0c;需要客服帮你解答疑惑。快递丢失时&#xff0c;需要客服帮忙找回。报名参加培训课程时&#xff0c;需要客服帮忙解答更适合的课程…… 基…

RTE 2024 隐藏攻略

大家好&#xff01;想必今年 RTE 大会议程大家都了解得差不多了&#xff0c;这将是一场实时互动和多模态 AI builder 的年度大聚会。 大会开始前&#xff0c;我们邀请了参与大会策划的 RTE 开发者社区和超音速计划的成员们&#xff0c;分享了不同活动的亮点和隐藏攻略。 请收…

InnoDB 存储引擎<一>InnoDB简介与MySQL存储架构及相关数据结构

目录 回顾MySQL架构 InnoDB简介 ​MySQL存储结构 回顾MySQL架构 对MySQL架构图的总结: MySQL服务器是以网络服务的方式对外提供数据库服务的&#xff0c;我们使用的应用程序以及客户端统称为外部程序。 外部程序通过发送网络请求的方式来连接MySQL服务器&#xff0c;这时首先每…

SpringBoot启动报错java.nio.charset.MalformedInputException: Input length =1

启动springboot项目时&#xff0c;出现了以下报错&#xff1a; defaultPattern_IS_UNDEFINEDdefaultPattern_IS_UNDEFINEDdefaultPattern_IS_UNDEFINEDjava.lang.IllegalStateException: Failed to load property source from location classpath:/application-local.yamlat o…

使用pytest单元测试框架执行单元测试

Pytest 是一个功能强大且灵活的 Python 单元测试框架&#xff0c;它使编写、组织和运行测试变得更加简单。以下是 Pytest 的一些主要特点和优点&#xff1a; 简单易用&#xff1a;Pytest 提供了简洁而直观的语法&#xff0c;使编写测试用例变得非常容易。它支持使用 assert 语…

《皮革制作与环保科技》是什么级别的期刊?是正规期刊吗?能评职称吗?

​问题解答 问&#xff1a;《皮革制作与环保科技》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的正规学术期刊。 问&#xff1a;《皮革制作与环保科技》级别&#xff1f; 答&#xff1a;国家级。主管单位&#xff1a;中国轻工业联合会 …

软考:CORBA架构

CORBA过时了吗 CORBA指南 个人小结&#xff1a; IPC&#xff0c;进程间通信&#xff0c;Socket应用在不同机器之间的通信 RPC是一种技术思想而非一种规范 但站在八九十年代的当口&#xff0c;简单来说&#xff0c;就是我在本地调用了一个函数&#xff0c;或者对象的方法&…

uvm_info、uvm_warning,uvm_error、uvm_fatal

1、warning/error/fatal调试语句 调试语句除了uvm_info&#xff0c;UVM内部根据问题的严重性&#xff08;severity&#xff09;由低到高&#xff0c;还引入了uvm_warning/uvm_error/uvm_fatal。 它们也是UVM预定义的宏&#xff0c;格式跟umv_info很像&#xff0c;只是不再需要…

int main(int argc,char* argv[])详解

#include <stdio.h> //argc 是指命令行输入参数的个数; //argv[]存储了所有的命令行参数, //arg[0]通常指向程序中的可执行文件的文件名。在有些版本的编译器中还包括程序文件所在的路径。 //如:"d:\Production\Software\VC_2005_Test\Win32控制台应用程序\Vc_T…