通过华为eNSP验证聚合路由

实验指令

R1 一接口接R2二接口
R1 二接口接R2三接口
R1 三接口接R3一接口

R1

int eth-trunk 1
mode lacp
max ac 2
trunckport giga 0/0/1 to 0/0/3
lacp prio 30000
dis eth-trunck 1
dis int eth-trunck 1

R2

int eth-trunk 1
mode lacp
max ac 2
trunckport giga 0/0/1 to 0/0/3
dis eth-trunck 1
dis int eth-trunck 1

说明

  • int eth-trunk 1: 进入以太网聚合口1的配置模式。
  • mode lacp: 设置聚合模式为LACP(Link Aggregation Control Protocol),也可以选择静态LAG(Static Link Aggregation Group)模式。
  • max ac 2: 设置最大活动链路数为2。
  • trunckport giga 0/0/1 to 0/0/3: 将千兆以太网端口0/0/1到0/0/3加入聚合口1。
  • lacp prio 30000: 设置LACP协议优先级为30000。
  • dis eth-trunck 1: 显示聚合口1的信息。
  • dis int eth-trunck 1: 显示聚合口1的接口信息。

什么决定主动端

在LACP(Link Aggregation Control Protocol)协议中,进行链路聚合的两个设备中的一个设备被称为主动端(Active),另一个被称为被动端(Passive)。

主动端和被动端之间的区别在于它们在LACP协议中的行为方式不同。主动端会主动向被动端发送LACP数据帧,通过这些数据帧来告知被动端链路聚合的相关信息。而被动端则只是在收到主动端的LACP数据帧后才会回应相应的信息。

在LACP协议中,主动端的选择通常是基于以下条件中的一种或几种:

物理端口的速率:速率更高的端口通常会被选为主动端。
物理端口的编号:编号更小的端口通常会被选为主动端。
配置的优先级:优先级更高的端口通常会被选为主动端。
随机选择:在以上条件都相同的情况下,可以随机选择一个设备作为主动端。

通过华为eNSP验证路由器转发机制

实验原理

问题描述:

  • 有两台 PC,分别命名为 PC1 和 PC2。

  • PC1 和 PC2 分别连接路由器 R 的 G1 和 G2 端口。

  • PC1 的 IP 地址为 172.168.1.1,PC2 的 IP 地址为 192.168.1.2。

  • 路由器 R 对应端口一的网关地址为 172.168.1.254,对应端口二的网关地址为 192.168.1.254。

  • 现在 PC1 通过 ping 命令要 ping 通 PC2。
    需要解决的问题:

  • 在这个过程中,路由器 R 做了哪些事情?

  • 这个过程涉及到哪些网络层和传输层的协议?

  • 路由器如何进行 IP 地址和 MAC 地址表的学习?

实验过程

PC1到R:

  1. 发送一个ICMP包,源IP为172.168.1.1,目的IP为192.168.1.2,目的MAC为端口一的MAC地址。

  2. 路由器R收到ICMP包后,进行解包操作,读取目的IP地址,发现需要转发到另一个子网,于是进行路由查找。

  3. 路由器R查找路由表,发现目的IP地址192.168.1.2应该走端口二,于是将ICMP包转发给端口二。
    PC2回复ICMP:

  4. 端口二接收到ICMP包后,进行解包操作,读取目的MAC地址,发现该MAC地址为自己的MAC地址,于是进行目的IP地址查找。

  5. 端口二查找MAC表,发现没有192.168.1.2的MAC地址,于是发送ARP请求到端口一,请求192.168.1.2的MAC地址。

  6. PC2收到ARP请求后,返回ARP响应包,将自己的MAC地址告诉端口二。

  7. 端口二收到ARP响应包后,将目的MAC地址改为PC2的MAC地址,并将ICMP包转发给PC2。

  8. PC2接收到ICMP包后,进行回复操作,将ICMP包回复给PC1。
    PC2回复ICMP到PC1:

  9. PC2将ICMP包的源IP改为自己的IP地址,将目的IP改为172.168.1.1,将目的MAC改为端口二的MAC地址。

  10. 端口二接收到ICMP包后,进行解包操作,读取目的MAC地址,发现该MAC地址为自己的MAC地址,于是进行目的IP地址查找。

  11. 端口二查找MAC表,发现没有172.168.1.1的MAC地址,于是发送ARP请求到端口一,请求172.168.1.1的MAC地址。

  12. PC1收到ARP请求后,返回ARP响应包,将自己的MAC地址告诉端口一。

  13. 端口一收到ARP响应包后,将目的MAC地址改为PC1的MAC地址,并将ICMP包转发给PC1。

  14. PC1接收到ICMP包后,处理完毕。

总结

路由器对IP和MAC表的学习过程:

  • 当路由器收到一个数据包时,会将数据包中的源IP地址添加到相应的IP表中。但源MAC地址不会添加到MAC表,因为他的MAC表只记录端口MAC不会记录其他设备的MAC
  • 当路由器需要将数据包转发到一个目的IP地址时,会查找IP表来确定该数据包应该从哪个端口转发出去。
  • 如果在MAC表中找不到该目的IP地址对应的MAC地址,则会发送ARP请求到该目的IP地址所在的子网中,请求该IP地址的MAC地址。
  • 当收到ARP响应包时,会将对应的MAC地址添加到MAC表中。

实验结果:

端口一抓包

端口二抓包
路由转发原理实验

通过华为eNSP验证SW转发机制

1. 前置知识

  • STP(Spanning Tree Protocol)
    是一种网络协议,它可以避免在具有冗余链路的网络拓扑中发生环路,从而避免广播风暴和数据包的重复发送,保证网络拓扑的正确性和稳定性。

    当网络中有多条路径到达同一个目的地时,就可能会出现环路,如果不采取措施,数据包就会在环路中不断地循环转发,形成广播风暴,导致网络拥塞和性能下降,甚至会导致网络瘫痪。为了避免这种情况,STP协议通过选择一条主路径(Root Port)并关闭其他路径(Blocked Port),形成一颗不带环路的树状拓扑结构,从而保证数据包在网络中的正确传输。

    STP协议的工作过程主要包括以下步骤:

    选举根节点:网络中选举一个节点作为根节点,并确定所有节点到根节点的最短路径。

    选举根端口:每个节点选举一个根端口,即到根节点的最短路径所连通的端口,其他端口将被关闭。

    选举设计端口:在非根节点中,选举一个到根节点路径最短的端口作为设计端口,其他端口将被关闭。

    建立端口状态:根据选举结果,将端口设置为根端口、设计端口或者阻塞端口,从而形成一个不带环路的树状拓扑结构。

    通过STP协议的运作,可以实现在具有冗余链路的网络拓扑中避免环路,确保数据包的正确传输,提高网络的可靠性和稳定性。

  • undo info-center enable"用于在华为网络设备上禁用信息中心功能。

  • dis mac-address 交换机系统识图使用,功能显示mac地址表

    实验原理

    场景:

  • 三台PC机分别连接到一台交换机上

  • PC1 IP地址为172.168.1.1, PC2 IP地址为172.168.1.2, PC3 IP地址为172.168.1.3

  • 子网掩码均为24位,分别连接1/2/3号交换机端口
    操作过程:

  1. 通过PC1 ping PC2,PC1不知道PC2的MAC地址,因此不能发ICMP包,而是发起ARP request包。
  2. 交换机接收到ARP request协议包,因为目的MAC地址是全F是广播,会采用BUM(Broadcast Unknown Multicast)泛洪除1号端口以外的所有端口(即2/3号端口)发送该ARP包。
  3. PC2收到该ARP包,回应ARP replay包附上自己的MAC地址,交换机帮助转发该包到PC1。(PC1第一次发送ARP request到SW时,SW已经学习了PC1的MAC地址,且本次ARP replay包中目的MAC是PC1的MAC 所以是单播)
  4. PC1得到了PC2的MAC地址,发起ICMP协议包,交换机学习存储PC1和PC2的MAC地址和端口。(存储源MAC地址和对应端口)
  5. 此时通过MAC表查到PC2的MAC地址对应2号端口,交换机直接单播该包到2号端口。
    总结:
  • 交换机会在接收到ARP包时进行广播,将该包发送到所有端口(除了发送方所在的端口)。
  • PC2收到ARP请求包后会回应ARP replay包附上自己的MAC地址,这样PC1就能获得PC2的MAC地址了。
  • 交换机在学习到MAC地址和端口的映射关系后,可以直接单播到目标主机所在的端口,避免了不必要的广播。
  • PC3对于非自己的ARP request包不会回,但会处理。

实验截图


SW的MAC表

SW端口1抓包

SW端口2抓包

SW端口3抓包

通过华为eNSP实验了解路由ping和非相同网段时,静态路由默认转发端口

在此之前我们需要了解一些基本操作和概念

  • 用户界面
  • 系统界面
  • 端口界面
  • 用户进入系统: sys(system)
  • 系统修改路由名:sysname your router name
  • 系统进入端口: int g/0/0/0、int e/0/0/0 代表端口类型 物理线
  • 端口界面配置ip:ip add ip 子网掩码
  • 端口界面删除ip配置:undo ip add ip 子网掩码
  • 端口界面启用端口:undo shutdown
  • 用户界面保存配置:save ——> Y
  • 任意界面查看当前配置:dis cur
  • 任意界面查看某一端口: dis int g/0/0/0

*ARP协议:
Q:ARP协议是通过ip地址在网段广播查找mac地址

A:是的,ARP协议(Address Resolution Protocol)的作用是将一个IP地址解析为相应的MAC地址。当一台主机要向另一台主机发送数据时,需要知道对方的MAC地址,以便将数据发送到正确的网卡上。

当一台主机要解析另一台主机的MAC地址时,它会首先查询本地的 ARP 缓存表,如果没有找到目标主机的IP地址对应的MAC地址,则会通过 ARP 协议在本地网络中广播一个 ARP 请求包,请求目标主机回复它的 MAC 地址。目标主机收到请求包后会将自己的 MAC 地址回复给源主机,源主机再将目标主机的 MAC 地址保存在本地 ARP 缓存表中,以便下次快速获取。

因此,ARP协议是通过IP地址在同一网段内进行广播查找对应的MAC地址,以实现数据包的正确传输。

SQL优化

序言如果说慢查询是让我们发现问题,那么对于SQL优化的则可以让我们分析和解决问题,而不至于对于发现的那些慢查询语句单发愁而无可奈何

第一节:SQL底层是如何工作的

序言: 要想优化SQ的语句必定需要先知道SQL工作原理,这样我们才知道从哪几个点切入
Q:查询执行一般包括那些步骤?
查询执行包括以下几个步骤:查询缓存、解析器、优化器、执行器和存储引擎。
Q: 这些步骤对应组件功能是哪些?
其中,查询缓存是一个可选的组件,它可以缓存查询结果以提高查询性能。当查询缓存被启用时,MySQL会检查查询缓存中是否有与当前查询语句相同的结果,如果有,则直接返回缓存中的结果而不执行查询。

解析器和分析器是用于解析查询语句和生成查询树的组件,优化器是用于生成最优执行计划的组件,执行器是用于执行查询和返回结果的组件,存储引擎是用于处理底层数据的组件。

Q:那么解析器和优化器有什么不一样?
MySQL中,解析器和分析器是两个不同的组件,它们虽然有一些相同的功能,但是在执行过程中的职责不同。

解析器的主要作用是将SQL语句转换为内部格式,以便后续的处理和执行。具体来说,解析器会进行语法检查、语义检查等操作,并将SQL语句转换为查询树或其他内部数据结构。解析器还会将SQL语句中的表名、列名等信息解析出来,并进行一些基本的优化操作,例如将子查询转换为连接查询。

分析器的主要作用是分析查询语句的结构和条件,并生成一个查询执行计划。分析器会对查询语句进行优化,以生成一个最优的查询计划。分析器会考虑多种因素,如索引的使用、表连接的顺序、表访问方式等,并生成多个可能的执行计划,最终选择代价最小的执行计划。

因此,解析器和分析器的主要区别在于,解析器负责将SQL语句转换为内部格式,而分析器负责对查询语句进行优化,并生成最优的查询执行计划。解析器和分析器都是MySQL的重要组件,它们共同协作,以实现对查询语句的解析和优化。

ChatGPT使用经验

尽管 ChatGPT很聪明,但是涉及到上下文和复杂条件代码列举例子时还是容易出错,最近就错误地解释了SQL的最左匹配原则,所以使用 ChatGPT进行辅助学习有一些需要注意的地方

尽可能保证上下文干净

如果是一个完全未知的领域和内容,请先问大纲,遵循是什么,怎么用,为什么依次提问,如果顺序有误,或者回答不理想请刷新 ChatGPT,或者新开对话,否则尽可能回答错误答案。

举代码例子说明时要小心

ChatGPT对于代理举例说明更容易出问题,尽可能保证上下文干净的情况下进行代码举例请求。

使用ChatGPT问题遵循循序渐进,由大到小

在使用ChatGPT中对问题进行追问时,容易过于深入,忽略了学习的层次,要注意追问的深度,避免在浅层次前缀概念都没有弄清楚的情况下过于深入,导致反复询问类似的一个问题而无法理解。

部分内容无法帮你分担模块,而只能帮你优化过程,即提升效果而不能减少总工作量

对应华为eNSP实验中验证路由器转发机制这块,通过我的描述,ChatGpt给出的直接答案是PC1直接因为找不到PC2 MAC地址而发了ARP到端口一,这和实际抓包得到的相差甚远,实际上因为路由器是三层设备,如果PC1 MAC表找不到PC2 MAC地址,会先通过ip协议转发到路由器端口。

如何使用MariaDB的慢查询做MySQL优化 联合索引 最左匹配原则

序言数据库慢查询优化是数据库使用中必须掌握的功能,与其让用户因为5s的长延迟而流逝,不如通过慢查询优化那些丑陋的SQL查询

实验版本:MariaDB 10.5

MariaDB开启慢查询条件

慢查询开启,需要通过配置文件,这个配置文件根据你的安装目录不同而不同,但是一般都是在C:\Program Files\MariaDB 10.5下。文件名称是my.ini
如果以上命令都无法查看 MariaDB 的配置文件路径,你可以尝试在 MariaDB 中执行 SHOW VARIABLES; 命令,查看其中是否有 basedir 和 datadir 参数的输出。basedir 参数指定 MariaDB 的安装路径,datadir 参数指定 MariaDB 数据库文件的存储路径,可以通过这些参数的值来推断 MariaDB 的配置文件路径。或者直接使用
SHOW VARIABLES LIKE 'basedir'

my.ini常见配置选项

MySQL/MariaDB的配置文件中有很多不同的选项,这些选项控制了数据库的各种行为。下面是一些常见的选项及其作用:

bind-address:指定数据库服务器监听的IP地址,可以是单个IP地址或IP地址的列表。
port:指定数据库服务器监听的端口号。
datadir:指定数据库文件存储的路径。
log_error:指定错误日志的路径。
slow_query_log_file:指定慢查询日志的路径。
max_connections:指定数据库服务器支持的最大连接数。
character_set_server:指定数据库服务器使用的默认字符集。
collation-server:指定数据库服务器使用的默认排序规则。
default-storage-engine:指定数据库服务器默认使用的存储引擎。
innodb_buffer_pool_size:指定InnoDB存储引擎使用的缓冲池大小。
query_cache_size:指定查询缓存的大小。
log_queries_not_using_indexes:启用后,记录未使用索引的查询。
这些选项只是MySQL/MariaDB配置文件中的一小部分,具体的选项还会根据不同的版本和使用场景而有所不同。

通过配置文件字段设置启用慢查询

要启用慢查询,需要在配置文件中设置以下参数:

slow_query_log:将该参数设置为1,开启慢查询日志。

slow_query_log_file:指定慢查询日志文件的路径和名称。

long_query_time:指定查询执行时间超过多少秒才被认为是慢查询

slow_query_log=1(MySQL用1)
slow_query_log = ON(mariaDB用ON)
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time=5

这将开启慢查询日志,并将查询执行时间超过5秒的查询记录到/var/log/mysql/mysql-slow.log文件中。

如果你在配置文件中没有指定慢查询日志文件的位置,MySQL会在默认情况下将慢查询日志文件存储在数据目录下,并按照主机名和日志文件类型进行命名,例如:[hostname].log。

在这种情况下,如果你的MySQL数据目录为/var/lib/mysql/,慢查询日志文件将存储在/var/lib/mysql/[hostname].log的位置。不过具体位置还取决于你的系统平台和MySQL版本。

在修改了配置文件后,需要重启数据库才能让配置生效。因此,您需要重启 MariaDB 10.5 以启用慢查询。修改了配置文件后,连接到数据库并不会使更改立即生效。

果您正在Windows操作系统上运行MariaDB 10.5,则可以使用以下方法重启MariaDB:

打开Windows命令提示符(CMD)或Windows PowerShell。

输入以下命令,以停止MariaDB服务:

net stop mariadb

输入以下命令,以启动MariaDB服务

net start mariadb

在 Windows 上启动 MariaDB 10.5,可以通过以下步骤完成:

打开命令提示符或 PowerShell。

使用 cd 命令进入 MariaDB 的 bin 目录,该目录通常位于 MariaDB 安装目录下。

执行以下命令启动 MariaDB 服务:

mysqld.exe --console

如果你在 Windows 上通过 cmd 启动了 MariaDB,关闭 cmd 窗口不会停止 MariaDB 服务的运行。MariaDB 会以服务的形式在后台运行,除非手动停止服务或者重启计算机。

确保使用慢查询成功

SHOW VARIABLES LIKE 'slow_query_log';

如果输出结果中的 Value 为 ON,表示慢查询日志已经开启了;如果为 OFF,则表示慢查询日志未开启。

参数被覆盖了修改的配置文件不是正在使用的配置文件

如果你在 Windows 系统中执行 mysql --help | grep "Default options" 命令遇到了 'grep' 不是内部或外部命令,也不是可运行的程序或批处理文件。 的错误提示,那么说明你的系统上没有安装 grep 命令。

在 Windows 系统中,你可以使用 findstr 命令来替代 grep 命令,例如:

mysql --help | findstr "Default options"

该命令会输出 MariaDB 配置文件的默认搜索路径,你可以根据该路径找到 MariaDB 的配置文件并修改它。

多个 查询、分组、排序、条件时为什么应该使用联合索引

在多个查询条件时,如果使用联合索引,可以减少I/O操作的次数,从而提高查询效率。同时,在分组和排序操作中,联合索引也能够有效地优化查询性能。

举个例子来说,假设我们有一个订单表,包含订单号、商品ID、订单日期、订单状态和订单金额等字段。如果我们经常需要按照订单日期和订单状态进行查询、分组和排序,那么可以创建一个联合索引,包括订单日期和订单状态两个字段。

这样,当我们执行类似于以下SQL查询时:

SELECT 订单日期, 订单状态, SUM(订单金额) 
FROM 订单表 
WHERE 订单日期 BETWEEN '2022-01-01' AND '2022-01-31' 
AND 订单状态 = '已付款' 
GROUP BY 订单日期, 订单状态 
ORDER BY 订单日期 DESC, 订单状态 ASC

数据库可以直接使用联合索引,根据订单日期和订单状态进行索引查找,从而快速定位到符合条件的数据行。这样就可以大大减少I/O操作的次数,提高查询效率,特别是在数据量较大的情况下效果更加明显。

如果没有创建联合索引,数据库需要扫描整张表来查找符合条件的数据行,从而导致查询效率下降。因此,在多个查询、分组、排序条件时,建议使用联合索引来优化查询性能。

如何设置联合索引呢?

设置联合索引需要使用CREATE INDEX语句,并在索引名称后指定需要建立索引的列名。例如,要为表users的name和age列建立联合索引,可以使用以下语句

CREATE INDEX idx_users_name_age ON users (name, age);

将在表users上创建一个名为idx_users_name_age的联合索引,该索引将同时包括name和age列。值得注意的是,联合索引的顺序非常重要,因为它们将按照建立索引时指定的顺序进行排序和搜索。因此,需要根据查询的需求和数据的特点来确定联合索引的列的顺序。

查询需去显式地指定联合索引吗?

查询时无需显式指定联合索引。当查询语句中的条件可以使用联合索引进行匹配时,数据库系统会自动选择使用联合索引。例如,如果一个联合索引包含了字段A和B,并且查询语句中包含了条件"WHERE A=xxx AND B=yyy",那么数据库系统会自动选择使用该联合索引进行查询。

前提是设置了联合索引才行吗?

是的,前提是你设置了联合索引,系统会自动选择最合适的索引。如果没有设置联合索引,系统将根据查询条件进行全表扫描,效率较低。因此,在需要联合查询的列上设置合适的联合索引,可以显著提高查询效率。

最左匹配原则简介

  • 最左匹配原则是指在使用多列索引进行查询时,数据库引擎只能使用索引中最左边的列来优化查询。如果查询中使用的列不是最左边的列,那么该索引就不能被用来优化查询,而是必须扫描整个表。这就是为什么在创建索引时,应该把最常用的列放在最左边。

最左匹配原则工作原理

CREATE TABLE mytable (
    id INT NOT NULL PRIMARY KEY,
    name VARCHAR(50),
    age INT,
    gender VARCHAR(10)
);

CREATE INDEX idx_name_age ON mytable (name, age);

SELECT * FROM mytable WHERE name='John' AND age=25;

在这个示例中,我们创建了一个名为 idx_name_age 的联合索引,该索引包括 name 和 age 两个字段。当我们查询 mytable 表时,使用了 name 和 age 两个条件。由于联合索引是按照多个字段的组合值排序的,所以查询引擎只需要在索引中查找 name='John' 的值,然后再查找该值中 age=25 的数据行,而不是扫描整个表来查找匹配的行,从而提高了查询的效率。

不满足最左匹配原则的情况(顺序错误)

比如只创建了name,age,gender的联合索引,使用如下查询语句:

SELECT * FROM mytable WHERE gender='male' AND age=25;

则MySQL不会使用该联合索引进行查询优化,因为最左前缀规则的原则是,必须按照联合索引中定义的顺序,从左到右匹配查询条件。在这个例子中,虽然gender和age都包含在联合索引中,但查询条件中先出现了gender,而不是age,因此MySQL无法使用该索引进行优化。

不满足最左匹配原则的情况(没有包含联合索引的最左边的列或一组顺序列)

比如你创建了name,age,gender的联合索引,使用如下查询

SELECT * FROM mytable WHERE age=25 and gender='male'

或者

SELECT * FROM mytable WHERE name='jake' and gender='male'

不会利用到该联合索引,因为第一行age和gender,第二行name和gender在联合索引中的位置是不满足最左匹配原则的。因此会导致全表扫描,不可以充分利用联合索引的优势,提高查询效率。

但是注意这个索引的查询效率可能不如创建一个单独的(age,gender)联合索引,因为它不能直接满足(age,gender)的联合查询。

因此,在创建联合索引时,应该根据实际的查询需求来确定索引列的顺序,以使得最常用的列在最左边,这样可以有效地提高查询性能。~~

总结最左匹配原则

最左匹配原则是指我创建了一个联合索引依次包含x,y,z字段。要想借助这个联合索引就必须满足查询中的字段出现顺序为x,y或者x,y,z否则就不能使用,对吗?

是的,您理解得很正确,最左匹配原则是指当一个联合索引包含多个列时,在查询中只使用联合索引的最左边的列或者最左边的一组列,才能利用该联合索引进行查找和排序。如果查询中的列没有遵循索引的顺序,则无法使用联合索引

如何写开题报告

序言:

开题报告不是想当然写的,在选题,主要内容,实施计划等都要严格的要求,对语言格式和语法都有要求。
每一个段落都以中心句开始,以总结句收尾,中间内容围绕中心句写。段落之间借助转折来进行起承转合连接上下文

选题

  1. 选题要细,说清楚意义何在
  2. 背景和意义,有大到小
  3. 国外研究的情况

问题和切入点

  1. 文献分析得到目前在paddle inference部署过程中的不足和同类研究的问题

计划和目标

  1. 体系
  2. 做什么
  3. 目标

绪论

  1. 理由 目的 背景

1研究背景和意义部分(3/4段 简单易懂)重要

  1. 大背景、具体研究方向、存在的问题、解决计划和后续意义
    道路灾害频发,对人们的出行造成了大量问题,传统检测手段检测存在大量问题,目前已经有了最新的视频检测ai,它可以解决xx问题,
    (逻辑关系,定量据系)国内有了xx个商业应用服务软件,但是还是存在大量问题,最多的问题是xx,占比百分之xx。
    (展示具体问题)点明技术点,文献支撑
    (说下研究情况,转折引出问题,解决了这个问题,有啥好处)
    目的:更具有学术性

2.国内外现状

搭个台子(专业词分析解释)介绍原理和问题,落到这个问题上,转折到解决这个问题上

3.国内外文献综述(大标题和小标题之间要有过渡段)重要

  1. 梳理历史把握总体情况
  2. 肯定别人的贡献,防止做了重复的内容,再做一下批判:细读文献,横向对比文献,列出各个文献在某些属性上的缺陷和问题,不要单纯列出文献
  3. 目前存在的问题和调整

    主要研究内容的写作

  • 大体方案:借助现有条件写计划(细细细,结果复现,细节,给图,给流程图让别人方便理解)
  • 分度计划:拆分问题,进度安排和计划
  • 确定可行性:有理有据,有流程图,对可行性有预研究

预期目标和研究成果

  1. 你新的地方在哪里?突出新颖和独特点,比如软件设计
  2. 预期的目标 ,预期的结果:软件著作专利

进度安排

  1. 文献调研时间,工具时间
  2. 先易后难,先少后多安排

已经完成的工作 重要

  1. 展示你的前期进展,进展不好会非常惨
  2. 已经完成的内容
    • paddle inference 推理的环境配置
    • 一个简单demo的运行
    • 一个同类型工程的运行
    • 项目的数据库设计情况
    • 项目的需求分析情况

参考文献的写作(新文献尽可能多,规范引用,针对具体点引用)

  • 不要乱引用

text传输页面

这篇论文提出了以下具体的可变导向车道优化方法:

  1. 确定可变导向车道设置阈值的方法,并改善了可变导向车道自适应控制系统。
  2. 对交叉口转向交通流不均衡特性及不均衡程度进行研究,分析了交叉口进口道交通流的运行与排队特征,阐述了交叉口供需间的不匹配关系,并进一步分析转向交通分布的各类影响因素,总结了转向交通不均衡特性。
  3. 研究了设置可变导向车道的阈值与最佳范围。通过调查国内典型城市可变导向车道的设置,将其设置形式分为三类进行了阐述,总结了交叉口设置可变导向车道需满足的渠化条件、交通条件及信号控制条件;为确定设置可变导向车道的流量临界条件及最佳范围,本文以左转可变导向车道为例,将可变导向车道设置前后进口道车均延误相等作为目标,构建等车均延误模型,求解得左转流量比例阈值及最佳范围,并通过实例验证了方法的可行性。

(参考页码:摘要第一段、第二段;第一章绪论第二节、第三节)

好的,具体讲一下阈值方法。本文提出的阈值方法是针对左转可变导向车道的设置而言的。该方法通过构建等车均延误模型,利用试值法对模型进行求解,绘制阈值曲线图,确定左转流量比例阈值及最佳范围。

具体流程如下:

  1. 得到交叉口数据,包括交叉口车道数N、设置可变导向车道前后车道组车道数、信号周期时长C、绿信比、饱和流率等参数。
  2. 给定一组判别条件值即左转流量和直行流量,代入等车均延误模型中计算设置可变导向车道前后进口道各转向车道组车均延误。
  3. 保持直行流量不变,不断改变左转流量,直到确定满足式(3-4)的左转流量值,并标记这组流量值。
  4. 改变直行车流量,然后返回步骤2,不断重复后得到满足式(3-4)的不同流量组合。
  5. 将直行流量作为横坐标,左转流量作为纵坐标,在坐标系中标记各个流量组合,并对组合值进行拟合即可绘制阈值曲线。

通过上述步骤可以得到设置可变导向车道前后的阈值曲线图。该图将坐标系分为两部分:上部分表示设置可变导向车道后车均延误减小,下部分表示设置可变导向车道后车均延误增大。通过该曲线图可以判断一个交叉口是否应该设置可变导向车道。当实际交叉口转向流量在满
细讲第一点
好的,我来详细讲一下第一点,即确定可变导向车道设置阈值的方法,并改善了可变导向车道自适应控制系统。

本文提出的方法是基于等车均延误模型,通过试值法求解得到左转流量比例阈值及最佳范围。具体步骤如下:

  1. 首先,得到交叉口数据,包括交叉口车道数N、设置可变导向车道前后车道组车道数、信号周期时长C、绿信比、饱和流率等参数。
  2. 然后,将原本交叉口渠化条件作为不设置可变导向车道时的情况,一条直行车道变为左转车道作为设置后情况。
  3. 接着,给定一组判别条件值即左转流量和直行流量,代入等车均延误模型中计算设置可变导向车道前后进口道各转向车道组车均延误。
  4. 保持直行流量不变,不断改变左转流量,直到确定满足式(3-4)的左转流量值,并标记这组流量值。
  5. 改变直行车流量,然后返回步骤3和4,不断重复后得到满足式(3-4)的不同流量组合。
  6. 将直行流量作为横坐标,左转流量作为纵坐标,在坐标系中标记各个流量组合,并对组合值进行拟合即可绘制阈值曲线。

通过上述步骤可以得到设置可变导向车道前后的阈值曲线图。该图将坐标系分为两部分:上部分表示设置可变导向车道后车均延误减小

机器学习-静态图和动态图的区别

主要内容如下

  • 什么是静态图
  • 什么是动态图
  • 什么是优化器,优化器是干什么的?
  • 静态图的弊端
  • 动态图的动态计算图是什么意思,可否修改动态图实现动态计算图的底层机制
    举一个简单例子展示下动态图和静态图尽可能简单
    假设我们要用 TensorFlow 实现一个简单的线性回归模型 y = wx + b,其中 w 和 b 是需要学习的参数,x 是输入数据。

在静态图中,我们需要定义计算图,并在图中定义变量 w 和 b,如下所示:

python
Copy code
import tensorflow as tf

定义计算图

graph = tf.Graph()
with graph.as_default():

定义变量

w = tf.Variable(0.0, name='w')
b = tf.Variable(0.0, name='b')

# 定义输入和输出
x = tf.placeholder(tf.float32, name='x')
y = tf.placeholder(tf.float32, name='y')
y_pred = w * x + b

# 定义损失函数和优化器
loss = tf.reduce_mean(tf.square(y - y_pred))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train_op = optimizer.minimize(loss)

在上面的代码中,我们先定义了一个计算图 graph,然后在图中定义了变量 w 和 b,输入和输出 x、y 和 y_pred,损失函数 loss 和优化器 optimizer。最后,我们使用 train_op 来进行梯度下降优化。

在动态图中,我们不需要事先定义计算图,可以直接使用 TensorFlow 的函数来定义模型,如下所示:

python
Copy code
import tensorflow as tf

定义模型

w = tf.Variable(0.0, name='w')
b = tf.Variable(0.0, name='b')
x = tf.placeholder(tf.float32, name='x')
y = tf.placeholder(tf.float32, name='y')
y_pred = w * x + b

定义损失函数和优化器

loss = tf.reduce_mean(tf.square(y - y_pred))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train_op = optimizer.minimize(loss)
在上面的代码中,我们直接定义了变量 w 和 b,输入和输出 x、y 和 y_pred,损失函数 loss 和优化器 optimizer,然后使用 train_op 来进行梯度下降优化。

需要注意的是,在上面的代码中,我们使用了 TensorFlow 的变量来定义 w 和 b。这些变量在每次迭代中都会被更新,从而使模型能够逐渐逼近最优解。因此,无论是在动态图还是静态图中,我们都需要定义变量来存储需要学习的参数。

pp oo
静态图例子中似乎只有一层神经网络,至少我看起来是这样,还有我可以认为w和b是某种意义上的偏置和权重吗?
是的,静态图的例子中只包含了一个神经网络的结构,其中只有一层权重和一层偏置。在静态图中,我们需要手动定义整个计算图的结构,包括输入、输出、变量、损失函数和优化器等。因此,静态图相对来说更加复杂,但是可以提供更好的性能和灵活性。

对于 w 和 b,可以把它们理解为神经网络中的权重和偏置。在线性回归模型中,w 代表输入特征和输出之间的权重,b 代表偏置,可以看作是一个常量。在训练过程中,我们需要不断更新 w 和 b 的值,以最小化损失函数。

pp oo
嗯嗯,静态图的损失函数我可以非常轻松的理解,我认为train_op = optimizer.minimize(loss)这一行代码封装了大量底层逻辑,比如我只看到传入了一个损失函数计算得到的值但具体是如何进行梯度下行化的我并看不到1,但是我知道他一定按照某种算法修改了w和x的值,只不过封装后我看不到,对啊没?
是的,你的理解是正确的。在静态图中,我们只需要定义损失函数,然后使用优化器对象的 minimize 方法来最小化损失函数,框架会自动进行梯度计算和参数更新等底层操作。虽然我们看不到具体的实现细节,但是我们可以确定优化器对象会按照某种算法来更新模型参数,以最小化损失函数。所以,使用静态图可以更加方便地进行模型训练,但是可能会牺牲一定的灵活性。

pp oo
所以最小化损失函数这行是预定义的我们作为开发者只能简单地去调用接口没法去修改他的底层逻辑和实现对吗?
是的,最小化损失函数的底层逻辑是由优化器对象实现的,我们无法直接修改其底层逻辑。不过,我们可以通过调整优化器对象的超参数(如学习率、动量等)来影响参数更新的方式和速度。此外,一些深度学习框架(如 TensorFlow)还提供了自定义优化器的接口,可以根据需求自行实现优化器的底层逻辑。

pp oo
优化器的顾名思义就是借助损失函数计算得到的值用来优化权重和偏置的对吧
是的,优化器的作用就是根据损失函数计算出的损失值来更新模型的权重和偏置,以使模型能够更好地拟合训练数据。不同的优化器使用的更新策略有所不同,例如随机梯度下降法、动量法、自适应学习率法等,这些算法会根据损失函数的梯度信息来计算出参数的更新方向和大小。优化器的选择和调整对于模型的性能和训练速度都有着很重要的影响。

那么动态图相对静态图灵活性更高对吗?如果以上面的例子举例是那几行代码呢?

是的,相对于静态图,动态图具有更高的灵活性,因为它允许我们在运行时动态地构建计算图,并且可以在图中使用控制流语句(如条件语句、循环语句等),从而更加灵活地实现复杂的模型结构。

以之前的例子为例,动态图的代码相对简单,可以像下面这样实现:

lua
Copy code
import torch

x = torch.tensor([[1.0, 2.0]])
w = torch.tensor([[2.0], [1.0]])
b = torch.tensor([1.0])

for i in range(100):
y = x.mm(w) + b
loss = (y - torch.tensor([[4.0]])).pow(2).sum()
print(loss)
loss.backward()
with torch.nograd():
w -= 0.1 w.grad
b -= 0.1
b.grad
w.grad.zero
()
b.grad.zero_()
在动态图中,我们可以直接使用 PyTorch 提供的张量计算库来实现模型计算,同时使用 Python 语言中的流程控制语句来实现训练过程的迭代,这使得代码的可读性和灵活性都得到了很好的保证。

pp oo
loss.backward()是反向传递函数启的作用和静态图优化器类似对吗?
是的,loss.backward()函数是PyTorch中的反向传播函数,它的作用类似于静态图中的优化器,用来计算参数的梯度并更新参数。在动态图中,反向传播函数会自动跟踪计算图中的梯度信息,从而实现灵活的动态计算图。

pp oo
我注意到with torch.no_grad()这行代码里面似乎定义了权重和偏置的变动幅度,而静态图中没有这些代码,这就是为什么静态图不如动态图灵活,对吗?
with torch.no_grad() 是一个上下文管理器,用于告诉PyTorch在此上下文中不进行梯度计算。在这个上下文管理器中,我们可以手动更新模型的参数,而不会影响模型的梯度计算。

在静态图中,我们需要在定义计算图时指定每个变量的形状和数据类型,这就限制了模型的灵活性。而在动态图中,模型的计算图是在运行时动态构建的,因此我们可以更灵活地改变模型的结构和参数。

所以可以说,在动态图中,我们可以更加灵活地改变模型的参数,并且可以使用Python原生的流程控制语句(如循环、条件语句等),使得模型的定义更加直观、简洁。而在静态图中,我们需要在定义计算图时对所有变量进行预定义,这就限制了模型的灵活性和可读性。

pp oo
我还是不明白静态图中模型技术图是动态运行时动态构建的这个概念,可以用代码展示下吗?
在静态图中,模型的计算图是在编译时就被构建好了,而在动态图中,模型的计算图是在运行时根据输入数据动态构建的。

下面是一个简单的示例代码,使用 TensorFlow 实现了一个静态图和一个动态图的计算:

python
Copy code
import tensorflow as tf

定义输入占位符

x = tf.placeholder(tf.float32, [None, 2])
y_true = tf.placeholder(tf.float32, [None, 1])

静态图

w1 = tf.Variable(tf.random_normal([2, 4]))
b1 = tf.Variable(tf.random_normal([4]))
h1 = tf.nn.relu(tf.matmul(x, w1) + b1)

w2 = tf.Variable(tf.random_normal([4, 1]))
b2 = tf.Variable(tf.random_normal([1]))
y_pred_static = tf.matmul(h1, w2) + b2

loss_static = tf.reduce_mean(tf.square(y_pred_static - y_true))

动态图

@tf.function
def model_dynamic(x):
w1 = tf.Variable(tf.random_normal([2, 4]))
b1 = tf.Variable(tf.random_normal([4]))
h1 = tf.nn.relu(tf.matmul(x, w1) + b1)

w2 = tf.Variable(tf.random_normal([4, 1]))
b2 = tf.Variable(tf.random_normal([1]))
y_pred_dynamic = tf.matmul(h1, w2) + b2

loss_dynamic = tf.reduce_mean(tf.square(y_pred_dynamic - y_true))
return y_pred_dynamic, loss_dynamic

x_sample = tf.random.normal([10, 2])
y_true_sample = tf.random.normal([10, 1])

y_pred_dynamic, loss_dynamic = model_dynamic(x_sample)

定义优化器和训练操作

optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train_op_static = optimizer.minimize(loss_static)

在动态图中,需要显式地调用优化器进行参数更新

@tf.function
def train_step_dynamic(x, y_true):
with tf.GradientTape() as tape:
y_pred_dynamic, loss_dynamic = model_dynamic(x)
gradients = tape.gradient(loss_dynamic, model_dynamic.variables)
optimizer.apply_gradients(zip(gradients, model_dynamic.variables))
return y_pred_dynamic, loss_dynamic

y_pred_dynamic, loss_dynamic = train_step_dynamic(x_sample, y_true_sample)
可以看到,在静态图中,模型的计算图是在编译时构建好的,可以直接使用 optimizer.minimize() 函数来进行优化;而在动态图中,模型的计算图是在运行时动态构建的,需要使用 tf.GradientTape() 来记录梯度信息,并且需要显式地调用优化器来进行参数更新。

pp oo
静态图构建好的模型是指什么?类似线性回归模型中 y = wx + b这种数学关系吗?
静态图构建好的模型通常是指一个计算图,该计算图由一些节点和边构成,每个节点代表一个操作,每条边代表数据流向。这些节点和边构成的计算图可以看作是一个预定义好的模型,每个节点的操作已经被固定下来,无法动态调整。我们可以通过填充计算图的输入来执行这个模型,并得到相应的输出结果。在这种情况下,线性回归模型中的 y = wx + b 确实可以看作是一个静态图的计算节点,其中的 w 和 b 可以看作是节点的参数。

pp oo
我了解了,计算图真的只是一个图而已,这个图给我们展示了可能简单可能复杂的运算关系,总之是一系列相互关联的计算,画出来就成为了一个图
正是的,计算图本质上就是一张图,它用节点和边来表示计算操作和数据流动的关系,展示了计算的过程和依赖关系。在神经网络中,节点通常表示神经元,边则表示神经元之间的连接和传递的数据。计算图的好处是能够清晰地描述计算流程和依赖关系,方便进行优化和并行化等操作。

pp oo
动态图是不是封装底层的动态计算图
是的,动态图是指在计算图中,每个操作都是在需要的时候动态构建的,每个操作的输出都可以作为另一个操作的输入,这种方式下,计算图是动态生成的,可以根据数据和代码的不同来生成不同的计算图,从而使得模型更加灵活。动态图通常被用于一些需要动态构建计算图的任务,如自然语言处理和强化学习等领域。在PyTorch中,动态图是通过PyTorch的Autograd自动求导机制实现的。

pp oo
我们可以修改底层的计算图生成机制吗?还是说我们只能简单地调用动态图
在动态图中,可以通过编写 Python 代码来构建计算图,因此我们可以直接修改计算图的生成机制,从而实现更加灵活和个性化的计算图。此外,动态图还提供了一些底层 API,可以更加细粒度地控制计算图的构建和执行。但需要注意的是,直接修改动态图的底层机制需要对 PyTorch 的底层代码有一定的了解,所以并不是所有开发者都需要或者能够修改动态图的底层实现。