图节点嵌入相关算法学习笔记

news2024/11/23 21:17:59

引言

本篇笔记为coggle 2月打卡任务,正好也在学习cs224w,干脆就一起做了,以下是任务列表:

任务名称难度
任务1:图属性与图构造低、1
任务2:图查询与遍历低、2
任务3:节点中心性与应用中、2
任务4:图节点嵌入算法(DeepWalk/node2vec)高、3
任务5:图节点嵌入算法:LINE/SDNE高、3
任务6:图节点嵌入算法:GraphGAN高、3

task1 图属性与图构造

  • 步骤1:导入networkx
  • 步骤2:加载Wiki数据集,包含来自 19 个类别的 2405 个文档和它们之间的 17981个边。
  • 步骤3:使用networkx构造上述有向图
import pandas as pd
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt

# 两列,分别为节点id,节点类别
group = pd.read_csv('http://mirror.coggle.club/dataset/graph-wiki/group.txt.zip', sep='\t', header=None)

# 两列,分别为出发节点id,目的节点id
graph = pd.read_csv('http://mirror.coggle.club/dataset/graph-wiki/graph.txt.zip', sep='\t', header=None)

g = nx.DiGraph()

# 只添加前100条边
g.add_edges_from(graph.values[:100])
nx.draw_spring(g)

# 添加所有数据
g = nx.DiGraph()
g.add_edges_from(graph.values[:])

在这里插入图片描述

task2 图查询与遍历

  1. 步骤1:使用networkx对Wiki数据集进行如下统计
    • 节点个数、边个数
    • 节点度平均
    • 存在指向自身节点的个数
  2. 步骤2:对节点1397进行深度和广度遍历,设置搜索最大深度为5
  3. 步骤3:判断节点1573与节点1397之间是否存在联通性
# 边个数 节点个数
g.number_of_edges(), g.number_of_nodes()

# 度均值
np.mean([x[1] for x in list(g.degree())])

# 对节点1397的深度5内进行深度和广度遍历
nx.dfs_tree(g, 1397, 5).nodes()
nx.bfs_tree(g, 1397, 5).nodes()

# 节点1573与节点1397之间的路径
list(nx.connectivity.node_disjoint_paths(g, 1573, 1397))
"""
[[1573, 2337, 489, 708, 1525, 1397],
 [1573, 280, 696, 1610, 1445, 1397],
 [1573, 445, 2395, 750, 1397],
 [1573, 933, 1455, 1401, 1412, 1397]]
"""

task3 节点中心性与应用

本task的数据为:

# 文章1
'''
一纸四季报,令芯片巨头英特尔一夜间股价重挫近6.5%,市值蒸发80亿美元,再度被AMD反超。

这份严重缩水的财报显示,英特尔在去年四季度营收大降32%至140亿美元,是2016年以来最低单季收入;净利润由三季度的10.2亿美元转为近7亿美元净亏损;毛利率更从2021年四季度的53.6%大幅下降至39.2%。

此番业绩“跳水”并非英特尔一家的一时失利,在全球PC出货量整体下滑的背景下,包括英特尔、AMD、英伟达、高通在内的芯片企业,均在过去一年里出现不同程度的收入与利润下滑,但英特尔的确是其中的重灾区。
'''

# 文章2
'''
2021年,成都地区生产总值已经超过1.99万亿元,距离2万亿门槛仅咫尺之间。在去年遭受多轮疫情冲击及高温限电冲击的不利影响下,2022年,成都市实现地区生产总值20817.5亿元,按可比价格计算,比上年增长2.8%。

成都因此成为第7个跨过GDP2万亿门槛的城市。目前,GDP万亿城市俱乐部中形成了4万亿、3万亿、2万亿和万亿这四个梯队。上海和北京在2021年跨过了4万亿,深圳2021年跨过了3万亿,重庆、广州、苏州和成都则是2万亿梯队。

在排名前十的城市中,预计武汉将超过杭州。武汉市政府工作报告称,预计2022年武汉地区生产总值达到1.9万亿元左右。而杭州市统计局公布的数据显示,杭州2022年地区生产总值为18753亿元。受疫情影响,武汉在2020年GDP排名退居杭州之后。
'''


# 文章3
'''
据报道,美国证券交易委员会(SEC)与特斯拉首席执行官埃隆·马斯克之间又起波澜。SEC正对马斯克展开调查,主要审查内容是,马斯克是否参与了关于特斯拉自动驾驶软件的不恰当宣传。

据知情人士透露,该机构正在调查马斯克是否就驾驶辅助技术发表了不恰当的前瞻声明。

特斯拉在2014年首次发布了其自动驾驶辅助功能,公司声称该功能可以让汽车在车道内自动转向、加速和刹车。目前所有特斯拉车辆都内置了该软件。
'''

步骤1:筛选度最大的Top10个节点,并对节点深度1以内的节点进行可视化;

# 筛选度最大的Top10个节点,并对节点深度1以内的节点进行可视化;
g_degree = pd.DataFrame(g.degree()).sort_values(by=1)
g_degree = g_degree.iloc[-10:]

selected_nodes = []
for node in g_degree[0].values:
    selected_nodes += list(nx.dfs_tree(g, node, 1).nodes())

nx.draw_spring(g.subgraph(selected_nodes), node_size=3)

在这里插入图片描述


步骤2:使用PageRank筛选Top10个节点,并对节点深度1以内的节点进行可视化;

# 使用PageRank筛选Top10个节点,并对节点深度1以内的节点进行可视化
g_pagerank = pd.DataFrame.from_dict(nx.pagerank(g), orient='index')
g_pagerank = g_pagerank.sort_values(by=0)

g_pagerank = g_pagerank.iloc[-10:]
selected_nodes = []
for node in g_pagerank[0].index:
    selected_nodes += list(nx.dfs_tree(g, node, 1).nodes())

nx.draw_spring(g.subgraph(selected_nodes), node_size=3)

在这里插入图片描述

步骤3:文本关键词提取算法RAKE

这里以文章一为例,先将上述文章1的内容规整一下:

content = "一纸四季报,令芯片巨头英特尔一夜间股价重挫近6.5%,市值蒸发80亿美元,再度被AMD反超。这份严重缩水的财报显示,英特尔在去年四季度营收大降32%至140亿美元,是2016年以来最低单季收入;净利润由三季度的10.2亿美元转为近7亿美元净亏损;毛利率更从2021年四季度的53.6%大幅下降至39.2%。此番业绩“跳水”并非英特尔一家的一时失利,在全球PC出货量整体下滑的背景下,包括英特尔、AMD、英伟达、高通在内的芯片企业,均在过去一年里出现不同程度的收入与利润下滑,但英特尔的确是其中的重灾区。"

然后使用RAKE算法对上述内容进行提取,并计算单词打分 wordDegree (w) / wordFrequency (w),以及统计每个文章Top10关键词:

import jieba
from collections import Counter

g2 = nx.Graph()
words = jieba.lcut(content)
words = [x for x in words if len(x) > 1]
for i in range(len(words)-2):
    for j in range(i-2, i+2):
        if i == j:
            continue
        g2.add_edge(words[i], words[j])

g2_node_gree = dict(g2.degree())
word_counter = dict(Counter(words))

g2_node_gree = pd.DataFrame.from_dict(g2_node_gree, orient='index')
g2_node_gree.columns = ['degree']

g2_node_gree['freq'] = g2_node_gree.index.map(word_counter)
g2_node_gree['score'] = g2_node_gree['degree'] / g2_node_gree['freq']

g2_node_gree.sort_values(by='score').index[-10:]

"""
['32%', '140', '2016', '以来', '最低', '单季', '收入', '利润', '缩水', '净利润']
"""

其余两个就不再详述,这里贴出结果为:

# ['增长', '2.8%', '成都', '2020', '成为', '超过', 'GDP2', '目前', '可比价格', '因此']
# ['主要', '审查', '内容', '参与', '关于', '软件', '所有', '宣传', '人士', '恰当']

步骤4:文本关键词提取算法TextRank

这里跟步骤三一样,直接给出代码为:

g2 = nx.Graph()

words = jieba.lcut(content)
words = [x for x in words if len(x) > 1]
for i in range(len(words)-2):
    for j in range(i-2, i+2):
        if i == j:
            continue
        g2.add_edge(words[i], words[j])

g2_node_gree = pd.DataFrame.from_dict(nx.pagerank(g2), orient='index')
g2_node_gree.columns = ['degree']
g2_node_gree = g2_node_gree.sort_values(by='degree')

三篇文章提取统计的结果为:

# ['39.2%', '四季', '一纸', 'AMD', '下滑', '四季度', '收入', '芯片', '亿美元', '英特尔']
# ['万亿元', '成都', '地区', '2021', '城市', '杭州', '武汉', '2022', '生产总值', '万亿']
# ['功能', '是否', '辅助', '调查', '恰当', 'SEC', '驾驶', '自动', '马斯克', '特斯拉']

下图是task任务下插入的一张图,但我不太清楚这张图怎么画的,就以上信息好像不怎么够,提取出来的6个关键词列表好像除了根据算法认定的词权重外似乎是没多大关系?之后再研究一下:
在这里插入图片描述

当然,这里我尝试了一些简单的方式,比如我看到有直接用相关性的,这里我大概修改了一下代码,为:

G = nx.Graph()

keywords_list = [
    ['39.2%', '四季', '一纸', 'AMD', '下滑', '四季度', '收入', '芯片', '亿美元', '英特尔'],
    ['功能', '是否', '辅助', '调查', '恰当', 'SEC', '驾驶', '自动', '马斯克', '特斯拉'],
    ['万亿元', '成都', '地区', '2021', '城市', '杭州', '武汉', '2022', '生产总值', '万亿'],
    ['32%', '140', '2016', '以来', '最低', '单季', '收入', '利润', '缩水', '净利润'],
    ['增长', '2.8%', '成都', '2020', '成为', '超过', 'GDP2', '目前', '可比价格', '因此'],
    ['主要', '审查', '内容', '参与', '关于', '软件', '所有', '宣传', '人士', '恰当']
]

# 定义一个函数来计算两个关键词列表之间的相关性
def similarity(list1, list2):
    # 计算两个列表之间的交集和并集
    intersection = set(list1) & set(list2)
    union = set(list1) | set(list2)
    
    # 计算交集与并集之比作为相关性度量
    return len(intersection) / len(union)

# 添加节点和边
for keywords in keywords_list:
    G.add_nodes_from(keywords)
for i in range(len(keywords_list)-1):
    for j in range(i+1, len(keywords_list)):
        # 计算两个关键词列表之间的相关性,并作为边的权重
        weight = similarity(keywords_list[i], keywords_list[j])
        # 只有当相关性大于0时才添加边
        if weight > 0:
            G.add_edge(keywords_list[i][0], keywords_list[j][0], weight=weight)

nx.draw(G, with_labels=True, font_weight='bold',
        node_color='skyblue',
        edge_color='gray')
plt.show()

有些丑,没有上图好看,就不贴出来献丑了,emmm,可以自己跑跑试试,因为我是两个算法针对三段文章提取出来的,所以就直接取交并,而没有用到分词出来的权重,虽然结果感觉上差不多,还是需要词之间的相关性,这个不知道怎么定义。

task4 图节点嵌入算法:DeepWalk/node2vec

这里两个算法的原理,我已经在前面两篇文章中做了详细推导与说明,为:

CS224W课程学习笔记(三):DeepWalk算法原理与说明

CS224W课程学习笔记(四):node2vec算法原理与说明

deepwalk

首先写出随机游走的采样序列算法:

import random
def deepwalk(G, walk_length):
    nodes = G.nodes()
    history_walks = []

    # 对于每个节点
    for node in nodes:

        # 从当前节点开始
        random_walk_length = [node]

        # 开始游走
        for i in range(walk_length-1):

            # 找到节点邻居
            neighbors = list(G.neighbors(node))

            # 排除已经游走的邻居
            neighbors = list(set(neighbors) - set(random_walk_length))    
            if len(neighbors) == 0:
                break

            # 随机挑选邻居
            random_neighbor = random.choice(neighbors)            
            random_walk_length.append(random_neighbor)

            # 从下一个邻居继续游走
            node = random_neighbor

        # 此节点的游走路径
        history_walks.append(random_walk_length)

    return history_walks

然后我们加载wiki数据集,并用50维做嵌入,生成节点类别:

g = nx.DiGraph()
# 构件图
g.add_edges_from(graph.values[:])
# 游走
history_walks = deepwalk(g, 100)

from gensim.models import Word2Vec
# 训练word2vec
w2v = Word2Vec(history_walks, vector_size=50, window=5)
# 节点类别,因为word2vec有单独节点次序
node_group = group.iloc[list(w2v.wv.key_to_index.keys())][1].values
"""
array([18, 18,  4, ..., 11,  2, 17])
"""

根据上面得到的节点类别做降维与使用TSNE算法可视化,对于TSNE算法,我在deepwalk笔记中对该概念和PCA降维进行了对比,具体可以看上述我引用出来的第三篇,这里不再详述,那代码为:

from sklearn.manifold import TSNE

tsne = TSNE(n_components=2)
tsne_data = tsne.fit_transform(w2v.wv.vectors)

import matplotlib.cm as cm
x = np.arange(20)
ys = [i+x+(i*x)**2 for i in range(20)]
colors = cm.rainbow(np.linspace(0, 1, len(ys)))

plt.scatter(
    tsne_data[:, 0], 
    tsne_data[:, 1],
    color=colors[node_group]
)

在这里插入图片描述

然后我们可以使用节点嵌入向量 + 逻辑回归进行训练,并记录验证集准确率:

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

# 划分数据集
x_tr, x_val, y_tr, y_val = train_test_split(
    w2v.wv.vectors, node_group, test_size=0.2, stratify=node_group
)

# 模型训练与验证,准确率0.535
model = LogisticRegression()
model.fit(x_tr, y_tr)
model.score(x_val, y_val)
"""
0.5642023346303502
"""

还行,比预先版本的0.535要高0.03,因为逻辑回归没有给默认参数,这点随机性可以理解,毕竟分高了,emmm。

node2vec

node2vec是一种综合考虑DFS邻域和BFS邻域的graph embedding方法。简单来说,可以看作是deepwalk的一种扩展,是结合了DFS和BFS随机游走的deepwalk。node2vec依然采用随机游走的方式获取顶点的近邻序列,不同的是node2vec采用的是一种有偏的随机游走。

这里将上述的labels和graph改动一下格式,因为原来是以zip文件转格式而来并且是以制表符为分隔,先wget下载文件后,解压运行如下代码:

import pandas as pd

df = pd.read_table("graph.txt", sep="\t")
df2 = pd.read_table("label.txt", sep="\t")

# 将制表符替换成空格
df = df.replace("\t", " ")
df.to_csv("train.txt",sep=" ",index=False)
df.to_csv("test.txt",sep=" ",index=False)

然后根据我上面第四篇笔记中,浅梦大佬开发的ge包进行训练,代码改为:

import numpy as np

from ge.classify import read_node_label, Classifier
from ge import Node2Vec
from sklearn.linear_model import LogisticRegression

import matplotlib.pyplot as plt
import networkx as nx
from sklearn.manifold import TSNE


def evaluate_embeddings(embeddings):
    # group = pd.read_csv('http://mirror.coggle.club/dataset/graph-wiki/group.txt.zip', sep='\t', header=None)
    X, Y = read_node_label('test.txt')
    tr_frac = 0.8
    print("Training classifier using {:.2f}% nodes...".format(
        tr_frac * 100))
    clf = Classifier(embeddings=embeddings, clf=LogisticRegression())
    clf.split_train_evaluate(X, Y, tr_frac)


def plot_embeddings(embeddings,):
    X, Y = read_node_label('test.txt')

    emb_list = []
    for k in X:
        emb_list.append(embeddings[k])
    emb_list = np.array(emb_list)

    model = TSNE(n_components=2)
    node_pos = model.fit_transform(emb_list)

    color_idx = {}
    for i in range(len(X)):
        color_idx.setdefault(Y[i][0], [])
        color_idx[Y[i][0]].append(i)

    for c, idx in color_idx.items():
        plt.scatter(node_pos[idx, 0], node_pos[idx, 1], label=c)
    plt.legend()
    plt.show()

在这里插入图片描述

使用逻辑回归进行测试,得到的分数为0.5883,即:

{'micro': 0.5883575883575883, 'macro': 0.459881682897527, 'samples': 0.5883575883575883, 'weighted': 0.5816291785521392, 'acc': 0.5883575883575883}

task5 图节点嵌入算法:LINE/SDNE

步骤1:使用LINE对Wiki数据集节点嵌入,维度为50维
步骤2:每个group中20%的节点作为验证集,剩余的作为训练集
步骤3:使用节点嵌入向量 + 逻辑回归进行训练,并记录验证集准确率
步骤4:使用SDNE重复上述操作
步骤5:使用t-SNE将节点的LINE/SDNE特征降维,绘制散点图,节点颜色使用group进行区分

task6 图节点嵌入算法:GraphGAN

  • 步骤1:使用GraphGAN对Wiki数据集节点嵌入,维度为50维
  • 步骤2:每个group中20%的节点作为验证集,剩余的作为训练集
  • 步骤3:使用节点嵌入向量 + 逻辑回归进行训练,并记录验证集准确率
  • 步骤4:使用t-SNE将节点的GraphGAN特征降维,绘制散点图,节点颜色使用group进行区分

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

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

相关文章

Spark计算框架入门笔记

Spark是一个用于大规模数据处理的统一计算引擎 注意:Spark不仅仅可以做类似于MapReduce的离线数据计算,还可以做实时数据计算,并且它还可以实现类似于Hive的SQL计算,等等,所以说它是一个统一的计算引擎 既然说到了Spar…

js 拖动--动态改变div的宽高大小

index.html 如下&#xff1a;&#xff08;可以新建一个index.html文件直接复制&#xff0c;打开运行&#xff09; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta http-equiv"X-UA-Compatible&qu…

Python tkinter -- 第18章 画布控件之窗口

18.2.22 create_window(position, **options) 可以在画布控件中放置其他tkinter控件。放置的方法就是使用窗口组件。一个窗口组件只能容纳一个控件。如果要放置多个控件&#xff0c;可以把这些控件作为Frame控件的子控件&#xff0c;将Frame控件放入窗口组件中&#xff0c;就可…

超简单 华为OD机试用Python实现 -【踢石头子,踢石子问题】(2023-Q1 新题)

华为OD机试题 华为OD机试300题大纲踢石头子,踢石子问题题目输入输出示例一输入输出Python 代码如下所示算法思路华为OD机试300题大纲 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:blog.csdn.net/hihell/categ…

ChatGPT似乎有的时候并不能搞懂Java的动态分派,你懂了吗?

目录 碎碎念 ChatGPT 中出现的问题 那么正确答案应该是什么呢&#xff1f; 分派的相关知识点总结&#xff1a; 分派是什么&#xff1f; 静态分派与动态分派&#xff1a; Java语言是静态多分派&#xff0c;动态单分派的&#xff1b; 静态分派&#xff1a;静态重载多分派…

追梦之旅【数据结构篇】——详解C语言实现二叉树

详解C语言实现二叉树~&#x1f60e;前言&#x1f64c;什么是二叉树&#xff1f;二叉树的性质总结&#xff1a;整体实现内容分析&#x1f49e;1.头文件的编写&#xff1a;&#x1f64c;2.功能文件的编写&#xff1a;&#x1f64c;1&#xff09;前序遍历的数值来创建树——递归函…

IGKBoard(imx6ull)-Input设备编程之按键控制

文章目录1- input子系统介绍2- input事件目录&#xff08;1&#xff09;struct input_event 结构体&#xff08;2&#xff09;type&#xff08;事件类型&#xff09;&#xff1a;&#xff08;3&#xff09;code&#xff08;事件编码&#xff09;&#xff08;4&#xff09;value…

【华为OD机试模拟题】用 C++ 实现 - 九宫格按键输入(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明九宫格按键输入题目输入输出示例一输入输出说明示例二输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高…

webp格式转换成png怎么转

相对于png 图片&#xff0c;webp比png小了45%&#xff0c;但是缺点是你压缩的时候需要的时间更久了&#xff1b;优点是体积小巧&#xff1b;缺点是兼容性不太好, 只有opera,和chrome支持&#xff0c;不仅如此在后期的编辑修改上也很多软件无法打开。所以我们通常要将webp格式转…

9.1 IGMPv1实验

9.4.1 IGMPv1 实验目的 熟悉IGMPv1的应用场景掌握IGMPv1的配置方法实验拓扑 实验拓扑如图9-7所示&#xff1a; 图9-7&#xff1a;IGMPv1 实验步骤 &#xff08;1&#xff09;配置IP地址 MCS1的配置 MCS1的IP地址配置如图9-8所示&#xff1a; 图9-8&#xff1a;MCS1的配置 …

xgboost学习-XGBoost的智慧

文章目录一、选择弱评估器&#xff1a;重要参数booster二、XGB的目标函数&#xff1a;重要参数objective三、求解XGB的目标函数四、参数化决策树 alpha&#xff0c;lambda五、寻找最佳树结构&#xff1a;求解 ω与T六、寻找最佳分枝&#xff1a;结构分数之差七、让树停止生长&a…

redis(10)事务和锁机制

Redis事务定义 Redis 事务是一个单独的隔离操作&#xff1a;事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中&#xff0c;不会被其他客户端发送来的命令请求所打断。 Redis 事务的主要作用就是串联多个命令防止别的命令插队。 Multi、Exec、discard Redis 事务中…

【数据挖掘实战】——应用系统负载分析与容量预测(ARIMA模型)

项目地址&#xff1a;Datamining_project: 数据挖掘实战项目代码 目录 一、背景和挖掘目标 1、问题背景 2、传统方法的不足 2、原始数据 3、挖掘目标 二、分析方法与过程 1、初步分析 2、总体流程 第一步&#xff1a;数据抽取 第二步&#xff1a;探索分析 第三步&a…

【华为OD机试模拟题】用 C++ 实现 - 内存池(2023.Q1)

最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 去重求和(2023.Q1) 文章目录 最近更新的博客使用说明内存池题目输入输出示例一输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:…

C++【string类用法详细介绍string类模拟实现解析】

文章目录string 类用法介绍及模拟实现一、string介绍二、string类常用接口1. string类对象的常见构造接口2.string类对象的常见容量接口3.string类对象的常见修改接口4. string类对象的常见访问及遍历接口5.string其他接口1.不常用查找接口2.字符替换3.字符串拼接4.字符串排序5…

纯x86汇编实现的多线程操作系统实践 - 第三章 BSP的守护执行

本章我们将详细讲解BSP剩下的执行代码&#xff0c;它们被安排在bp_32.asm文件中。bp_32.asm主要完成以下功能&#xff1a;系统中断初始化加载字符图形数据到内存区域将AP的启动代码和32位保护模式下的代码分别加载到内存中显示主界面以及系统启动信息向所有AP群发启动命令进入守…

linux 解压.gz文件 报错 gzip:stdin:not in gzip format(已解决)

目录 1、问题&#xff1a; 2、分析原因 3、解决办法 1、问题&#xff1a; 在解压一个以【.gz】&#xff08;注意不是.tar.gz&#xff09;结尾的压缩包时&#xff0c;遇到报错 【gzip&#xff1a;stdin&#xff1a;不是gzip格式】 翻译一下问题&#xff1a;【gzip&#xff1a;st…

纯x86汇编实现的多线程操作系统实践 - 第一章 系统整体结构说明

现代CPU都是多核系统&#xff0c;拥有多个执行内核&#xff08;即计算引擎&#xff09;&#xff0c;可并发执行不同的代码。在CPU众多的执行内核中&#xff0c;有一个为主执行内核&#xff08;BSP&#xff09;&#xff0c;在CPU上电后&#xff0c;该主执行内核会率先启动&#…

lighthouse-自定义Gatherer与Audits

这篇文章是Lighthouse的后续&#xff0c;之前介绍了 lighthouse的介绍和基本使用方法 Lighthouse组合Puppeteer检测页面 这两篇文章&#xff0c;在这两篇文章中介绍了lighthouse的整体架构和基本运行的逻辑&#xff0c;lighthouse默认也采集了足够丰富的数据供我们去分析页面的…

都在用 AI 生成美少女,而我却。。。

最近 AI 画画特别的火&#xff0c;你能从网上看到非常多好看的图片&#xff0c;于是我就开始了我的安装之旅&#xff0c;我看到的图是这样的。这样的。还有这样的。然后我就开始了我的 AI 安装生成计划。安装环境首先我们需要安装 Python 环境&#xff0c;因为这个需要显卡&…