活动介绍

CREATE TRIGGER Student_Count AFTER INSERT ON Student REFERENCING NEW TABLE AS DELTA FOR EACH STATEMENT INSERT INTO StudentInsertLog (Numbers) SELECT COUNT(*) FROM DELTA 报错> 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'REFERENCING NEW TABLE AS DELTA FOR EACH STATEMENT INSERT INT' at line 3

时间: 2025-08-04 11:46:35 浏览: 15
<think>我们正在处理MySQL创建触发器时的1064错误。错误信息指向了`REFERENCINGNEWTABLEFOREACHSTATEMENT`部分。根据引用[4]中提供的创建触发器的基本语法,MySQL的触发器语法可能与其他数据库(如Oracle)有所不同。从引用[4]中我们可以看到,在创建触发器的语法中,`REFERENCING`子句是可选的,但是请注意,这个语法可能是针对其他数据库(如PostgreSQL或Oracle)的,因为引用[2]中有一个Oracle触发器的例子使用了`REFERENCING`子句。然而,在MySQL中,触发器的语法是不支持`REFERENCING`子句的。根据引用[3]和引用[5]的内容,MySQL触发器的语法通常不包含`REFERENCING`子句。在MySQL中,我们通常使用`OLD`和`NEW`关键字来引用行数据,而不需要额外的别名。因此,错误的原因可能是:在MySQL中使用了其他数据库的触发器语法,而MySQL不支持`REFERENCING`子句。在MySQL中创建触发器的正确语法可以参考引用[4]的基本语法,但需要去掉`REFERENCING`子句,因为MySQL不支持。同时,我们注意到引用[4]的语法中包含了`REFERENCING`,这可能是一个通用的语法说明,但实际在MySQL中是不被支持的。所以,我们应该去掉`REFERENCINGNEWTABLEAS`这部分,并直接使用`NEW`和`OLD`来引用列。例如,如果你原来的触发器语句类似于:CREATETRIGGERtrigger_nameBEFOREUPDATEONtable_nameREFERENCINGNEWTABLEASNewestFOREACHROWBEGIN--一些操作END;那么在MySQL中应该写成:CREATETRIGGERtrigger_nameBEFOREUPDATEONtable_nameFOREACHROWBEGIN--使用NEW.column_name来引用新值--例如:SETNEW.column=...;END;注意:在MySQL中,触发器必须是行级触发器(FOREACHROW),而不支持语句级触发器(FOREACHSTATEMENT)。所以,你不能写`FOREACHSTATEMENT`,而必须使用`FOREACHROW`。因此,错误1064的解决方法是:1.移除`REFERENCING`子句。2.确保使用`FOREACHROW`(这是MySQL唯一支持的)。3.在触发器内部,使用`NEW.column_name`来引用新行,`OLD.column_name`引用旧行。例如,引用[2]中的Oracle触发器在MySQL中应该改写为:原Oracle触发器:CREATEORREPLACETRIGGERshow_score_changeBEFOREUPDATEONnewREFERENCINGnewASNewestFOREACHROWBEGIN:Newest.f2:=TO_CHAR(:newest.f1);END;在MySQL中,我们去掉`REFERENCING`子句,并使用`SET`语句直接给`NEW`赋值:DELIMITER//CREATETRIGGERshow_score_changeBEFOREUPDATEONnewFOREACHROWBEGINSETNEW.f2=TO_CHAR(NEW.f1);END;//DELIMITER;注意:在MySQL中,如果触发器体中有多条语句,需要使用`BEGIN...END`块,并且需要临时更改定界符(如上例中的`DELIMITER//`)。所以,请检查你的触发器语句,去掉`REFERENCING`子句,并确保使用`FOREACHROW`。此外,注意在触发器体内正确使用`NEW`和`OLD`。如果问题仍然存在,请提供具体的触发器创建语句,以便进一步分析。但根据你的错误信息,最可能的原因就是MySQL不支持`REFERENCING`子句和`FOREACHSTATEMENT`。因此,请将`FOREACHSTATEMENT`改为`FOREACHROW`,并去掉`REFERENCINGNEWTABLE...`部分。总结:MySQL触发器不支持`REFERENCING`子句,只支持行级触发器(FOREACHROW)。所以去掉这些不支持的语法即可。参考引用[4]的语法,但去掉其中MySQL不支持的部分(即`REFERENCING`子句)。</think> ### MySQL触发器创建报错1064问题解析 您遇到的1064错误是因为MySQL不支持`REFERENCING NEW TABLE FOR EACH STATEMENT`语法结构。这个错误主要是由两个不兼容的语法元素组合导致: 1. **MySQL不支持语句级触发器** MySQL只支持行级触发器(`FOR EACH ROW`),无法使用语句级触发器(`FOR EACH STATEMENT`) 2. **MySQL不支持REFERENCING子句** `REFERENCING`是Oracle/PostgreSQL等数据库的语法,MySQL中使用直接访问NEW/OLD伪记录 **解决方案:** 请改用标准MySQL触发器语法: ```sql DELIMITER // CREATE TRIGGER your_trigger_name BEFORE/AFTER INSERT/UPDATE/DELETE ON your_table FOR EACH ROW -- 必须使用行级触发 BEGIN -- 直接访问 NEW/OLD 伪记录 SET NEW.column = expression; -- 或 IF NEW.column <> OLD.column THEN ... END; // DELIMITER ; ``` **具体修正示例:** 若您需要实现引用[2]中的类似功能(更新前转换数据类型),在MySQL中应写为: ```sql DELIMITER // CREATE TRIGGER convert_value BEFORE UPDATE ON your_table FOR EACH ROW BEGIN SET NEW.f2 = CAST(NEW.f1 AS CHAR); -- MySQL使用CAST替代TO_CHAR END; // DELIMITER ; ``` **关键语法要点:** 1. 始终使用 `FOR EACH ROW`(MySQL唯一支持的触发粒度)[^4] 2. 直接通过 `NEW.column` 访问新值,`OLD.column` 访问旧值 3. 类型转换使用 `CAST()` 或 `CONVERT()` 函数 4. 多语句触发器必须使用 `DELIMITER` 更改结束符 5. 查看现有触发器使用 `SHOW TRIGGERS`[^3] > 重要提示:MySQL 5.7+要求有`SUPER`权限创建触发器,且触发器不能修改正在触发的表[^5]
阅读全文

相关推荐

/* 3966 * Notes on Program-Order guarantees on SMP systems. 3967 * 3968 * MIGRATION 3969 * 3970 * The basic program-order guarantee on SMP systems is that when a task [t] 3971 * migrates, all its activity on its old CPU [c0] happens-before any subsequent 3972 * execution on its new CPU [c1]. 3973 * 3974 * For migration (of runnable tasks) this is provided by the following means: 3975 * 3976 * A) UNLOCK of the rq(c0)->lock scheduling out task t 3977 * B) migration for t is required to synchronize *both* rq(c0)->lock and 3978 * rq(c1)->lock (if not at the same time, then in that order). 3979 * C) LOCK of the rq(c1)->lock scheduling in task 3980 * 3981 * Release/acquire chaining guarantees that B happens after A and C after B. 3982 * Note: the CPU doing B need not be c0 or c1 3983 * 3984 * Example: 3985 * 3986 * CPU0 CPU1 CPU2 3987 * 3988 * LOCK rq(0)->lock 3989 * sched-out X 3990 * sched-in Y 3991 * UNLOCK rq(0)->lock 3992 * 3993 * LOCK rq(0)->lock // orders against CPU0 3994 * dequeue X 3995 * UNLOCK rq(0)->lock 3996 * 3997 * LOCK rq(1)->lock 3998 * enqueue X 3999 * UNLOCK rq(1)->lock 4000 * 4001 * LOCK rq(1)->lock // orders against CPU2 4002 * sched-out Z 4003 * sched-in X 4004 * UNLOCK rq(1)->lock 4005 * 4006 * 4007 * BLOCKING -- aka. SLEEP + WAKEUP 4008 * 4009 * For blocking we (obviously) need to provide the same guarantee as for 4010 * migration. However the means are completely different as there is no lock 4011 * chain to provide order. Instead we do: 4012 * 4013 * 1) smp_store_release(X->on_cpu, 0) -- finish_task() 4014 * 2) smp_cond_load_acquire(!X->on_cpu) -- try_to_wake_up() 4015 * 4016 * Example: 4017 * 4018 * CPU0 (schedule) CPU1 (try_to_wake_up) CPU2 (schedule) 4019 * 4020 * LOCK rq(0)->lock LOCK X->pi_lock 4021 * dequeue X 4022 * sched-out X 4023 * smp_store_release(X->on_cpu, 0); 4024 * 4025 * smp_cond_load_acquire(&X->on_cpu, !VAL); 4026 * X->state = WAKING 4027 * set_task_cpu(X,2) 4028 * 4029 * LOCK rq(2)->lock 4030 * enqueue X 4031 * X->state = RUNNING 4032 * UNLOCK rq(2)->lock 4033 * 4034 * LOCK rq(2)->lock // orders against CPU1 4035 * sched-out Z 4036 * sched-in X 4037 * UNLOCK rq(2)->lock 4038 * 4039 * UNLOCK X->pi_lock 4040 * UNLOCK rq(0)->lock 4041 * 4042 * 4043 * However, for wakeups there is a second guarantee we must provide, namely we 4044 * must ensure that CONDITION=1 done by the caller can not be reordered with 4045 * accesses to the task state; see try_to_wake_up() and set_current_state(). 4046 */ 4047 4048 /** 4049 * try_to_wake_up - wake up a thread 4050 * @p: the thread to be awakened 4051 * @state: the mask of task states that can be woken 4052 * @wake_flags: wake modifier flags (WF_*) 4053 * 4054 * Conceptually does: 4055 * 4056 * If (@state & @p->state) @p->state = TASK_RUNNING. 4057 * 4058 * If the task was not queued/runnable, also place it back on a runqueue. 4059 * 4060 * This function is atomic against schedule() which would dequeue the task. 4061 * 4062 * It issues a full memory barrier before accessing @p->state, see the comment 4063 * with set_current_state(). 4064 * 4065 * Uses p->pi_lock to serialize against concurrent wake-ups. 4066 * 4067 * Relies on p->pi_lock stabilizing: 4068 * - p->sched_class 4069 * - p->cpus_ptr 4070 * - p->sched_task_group 4071 * in order to do migration, see its use of select_task_rq()/set_task_cpu(). 4072 * 4073 * Tries really hard to only take one task_rq(p)->lock for performance. 4074 * Takes rq->lock in: 4075 * - ttwu_runnable() -- old rq, unavoidable, see comment there; 4076 * - ttwu_queue() -- new rq, for enqueue of the task; 4077 * - psi_ttwu_dequeue() -- much sadness :-( accounting will kill us. 4078 * 4079 * As a consequence we race really badly with just about everything. See the 4080 * many memory barriers and their comments for details. 4081 * 4082 * Return: %true if @p->state changes (an actual wakeup was done), 4083 * %false otherwise. 4084 */ 4085 static int 4086 try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) 4087 { 4088 unsigned long flags; 4089 int cpu, success = 0; 4090 4091 preempt_disable(); 4092 if (p == current) { 4093 /* 4094 * We're waking current, this means 'p->on_rq' and 'task_cpu(p) 4095 * == smp_processor_id()'. Together this means we can special 4096 * case the whole 'p->on_rq && ttwu_runnable()' case below 4097 * without taking any locks. 4098 * 4099 * In particular: 4100 * - we rely on Program-Order guarantees for all the ordering, 4101 * - we're serialized against set_special_state() by virtue of 4102 * it disabling IRQs (this allows not taking ->pi_lock). 4103 */ 4104 if (!ttwu_state_match(p, state, &success)) 4105 goto out; 4106 4107 trace_sched_waking(p); 4108 WRITE_ONCE(p->__state, TASK_RUNNING); 4109 trace_sched_wakeup(p); 4110 goto out; 4111 } 4112 4113 /* 4114 * If we are going to wake up a thread waiting for CONDITION we 4115 * need to ensure that CONDITION=1 done by the caller can not be 4116 * reordered with p->state check below. This pairs with smp_store_mb() 4117 * in set_current_state() that the waiting thread does. 4118 */ 4119 raw_spin_lock_irqsave(&p->pi_lock, flags); 4120 smp_mb__after_spinlock(); 4121 if (!ttwu_state_match(p, state, &success)) 4122 goto unlock; 4123 4124 #ifdef CONFIG_FREEZER 4125 /* 4126 * If we're going to wake up a thread which may be frozen, then 4127 * we can only do so if we have an active CPU which is capable of 4128 * running it. This may not be the case when resuming from suspend, 4129 * as the secondary CPUs may not yet be back online. See __thaw_task() 4130 * for the actual wakeup. 4131 */ 4132 if (unlikely(frozen_or_skipped(p)) && 4133 !cpumask_intersects(cpu_active_mask, task_cpu_possible_mask(p))) 4134 goto unlock; 4135 #endif 4136 4137 trace_sched_waking(p); 4138 4139 /* 4140 * Ensure we load p->on_rq _after_ p->state, otherwise it would 4141 * be possible to, falsely, observe p->on_rq == 0 and get stuck 4142 * in smp_cond_load_acquire() below. 4143 * 4144 * sched_ttwu_pending() try_to_wake_up() 4145 * STORE p->on_rq = 1 LOAD p->state 4146 * UNLOCK rq->lock 4147 * 4148 * __schedule() (switch to task 'p') 4149 * LOCK rq->lock smp_rmb(); 4150 * smp_mb__after_spinlock(); 4151 * UNLOCK rq->lock 4152 * 4153 * [task p] 4154 * STORE p->state = UNINTERRUPTIBLE LOAD p->on_rq 4155 * 4156 * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in 4157 * __schedule(). See the comment for smp_mb__after_spinlock(). 4158 * 4159 * A similar smb_rmb() lives in try_invoke_on_locked_down_task(). 4160 */ 4161 smp_rmb(); 4162 if (READ_ONCE(p->on_rq) && ttwu_runnable(p, wake_flags)) 4163 goto unlock; 4164 4165 if (READ_ONCE(p->__state) & TASK_UNINTERRUPTIBLE) 4166 trace_sched_blocked_reason(p); 4167 4168 #ifdef CONFIG_SMP 4169 /* 4170 * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be 4171 * possible to, falsely, observe p->on_cpu == 0. 4172 * 4173 * One must be running (->on_cpu == 1) in order to remove oneself 4174 * from the runqueue. 4175 * 4176 * __schedule() (switch to task 'p') try_to_wake_up() 4177 * STORE p->on_cpu = 1 LOAD p->on_rq 4178 * UNLOCK rq->lock 4179 * 4180 * __schedule() (put 'p' to sleep) 4181 * LOCK rq->lock smp_rmb(); 4182 * smp_mb__after_spinlock(); 4183 * STORE p->on_rq = 0 LOAD p->on_cpu 4184 * 4185 * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in 4186 * __schedule(). See the comment for smp_mb__after_spinlock(). 4187 * 4188 * Form a control-dep-acquire with p->on_rq == 0 above, to ensure 4189 * schedule()'s deactivate_task() has 'happened' and p will no longer 4190 * care about it's own p->state. See the comment in __schedule(). 4191 */ 4192 smp_acquire__after_ctrl_dep(); 4193 4194 /* 4195 * We're doing the wakeup (@success == 1), they did a dequeue (p->on_rq 4196 * == 0), which means we need to do an enqueue, change p->state to 4197 * TASK_WAKING such that we can unlock p->pi_lock before doing the 4198 * enqueue, such as ttwu_queue_wakelist(). 4199 */ 4200 WRITE_ONCE(p->__state, TASK_WAKING); 4201 4202 /* 4203 * If the owning (remote) CPU is still in the middle of schedule() with 4204 * this task as prev, considering queueing p on the remote CPUs wake_list 4205 * which potentially sends an IPI instead of spinning on p->on_cpu to 4206 * let the waker make forward progress. This is safe because IRQs are 4207 * disabled and the IPI will deliver after on_cpu is cleared. 4208 * 4209 * Ensure we load task_cpu(p) after p->on_cpu: 4210 * 4211 * set_task_cpu(p, cpu); 4212 * STORE p->cpu = @cpu 4213 * __schedule() (switch to task 'p') 4214 * LOCK rq->lock 4215 * smp_mb__after_spin_lock() smp_cond_load_acquire(&p->on_cpu) 4216 * STORE p->on_cpu = 1 LOAD p->cpu 4217 * 4218 * to ensure we observe the correct CPU on which the task is currently 4219 * scheduling. 4220 */ 4221 if (smp_load_acquire(&p->on_cpu) && 4222 ttwu_queue_wakelist(p, task_cpu(p), wake_flags)) 4223 goto unlock; 4224 4225 /* 4226 * If the owning (remote) CPU is still in the middle of schedule() with 4227 * this task as prev, wait until it's done referencing the task. 4228 * 4229 * Pairs with the smp_store_release() in finish_task(). 4230 * 4231 * This ensures that tasks getting woken will be fully ordered against 4232 * their previous state and preserve Program Order. 4233 */ 4234 smp_cond_load_acquire(&p->on_cpu, !VAL); 4235 4236 trace_android_rvh_try_to_wake_up(p); 4237 4238 cpu = select_task_rq(p, p->wake_cpu, wake_flags | WF_TTWU); 4239 if (task_cpu(p) != cpu) { 4240 if (p->in_iowait) { 4241 delayacct_blkio_end(p); 4242 atomic_dec(&task_rq(p)->nr_iowait); 4243 } 4244 4245 wake_flags |= WF_MIGRATED; 4246 psi_ttwu_dequeue(p); 4247 set_task_cpu(p, cpu); 4248 } 4249 #else 4250 cpu = task_cpu(p); 4251 #endif /* CONFIG_SMP */ 4252 4253 ttwu_queue(p, cpu, wake_flags); 4254 unlock: 4255 raw_spin_unlock_irqrestore(&p->pi_lock, flags); 4256 out: 4257 if (success) { 4258 trace_android_rvh_try_to_wake_up_success(p); 4259 ttwu_stat(p, task_cpu(p), wake_flags); 4260 } 4261 preempt_enable(); 4262 4263 return success; 4264 } 分析并给出总结解释

static int 4085 try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) 4086 { 4087 unsigned long flags; 4088 int cpu, success = 0; 4089 4090 preempt_disable(); 4091 if (p == current) { 4092 /* 4093 * We're waking current, this means 'p->on_rq' and 'task_cpu(p) 4094 * == smp_processor_id()'. Together this means we can special 4095 * case the whole 'p->on_rq && ttwu_runnable()' case below 4096 * without taking any locks. 4097 * 4098 * In particular: 4099 * - we rely on Program-Order guarantees for all the ordering, 4100 * - we're serialized against set_special_state() by virtue of 4101 * it disabling IRQs (this allows not taking ->pi_lock). 4102 */ 4103 if (!ttwu_state_match(p, state, &success)) 4104 goto out; 4105 4106 trace_sched_waking(p); 4107 WRITE_ONCE(p->__state, TASK_RUNNING); 4108 trace_sched_wakeup(p); 4109 goto out; 4110 } 4111 4112 /* 4113 * If we are going to wake up a thread waiting for CONDITION we 4114 * need to ensure that CONDITION=1 done by the caller can not be 4115 * reordered with p->state check below. This pairs with smp_store_mb() 4116 * in set_current_state() that the waiting thread does. 4117 */ 4118 raw_spin_lock_irqsave(&p->pi_lock, flags); 4119 smp_mb__after_spinlock(); 4120 if (!ttwu_state_match(p, state, &success)) 4121 goto unlock; 4122 4123 #ifdef CONFIG_FREEZER 4124 /* 4125 * If we're going to wake up a thread which may be frozen, then 4126 * we can only do so if we have an active CPU which is capable of 4127 * running it. This may not be the case when resuming from suspend, 4128 * as the secondary CPUs may not yet be back online. See __thaw_task() 4129 * for the actual wakeup. 4130 */ 4131 if (unlikely(frozen_or_skipped(p)) && 4132 !cpumask_intersects(cpu_active_mask, task_cpu_possible_mask(p))) 4133 goto unlock; 4134 #endif 4135 4136 trace_sched_waking(p); 4137 4138 /* 4139 * Ensure we load p->on_rq _after_ p->state, otherwise it would 4140 * be possible to, falsely, observe p->on_rq == 0 and get stuck 4141 * in smp_cond_load_acquire() below. 4142 * 4143 * sched_ttwu_pending() try_to_wake_up() 4144 * STORE p->on_rq = 1 LOAD p->state 4145 * UNLOCK rq->lock 4146 * 4147 * __schedule() (switch to task 'p') 4148 * LOCK rq->lock smp_rmb(); 4149 * smp_mb__after_spinlock(); 4150 * UNLOCK rq->lock 4151 * 4152 * [task p] 4153 * STORE p->state = UNINTERRUPTIBLE LOAD p->on_rq 4154 * 4155 * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in 4156 * __schedule(). See the comment for smp_mb__after_spinlock(). 4157 * 4158 * A similar smb_rmb() lives in try_invoke_on_locked_down_task(). 4159 */ 4160 smp_rmb(); 4161 if (READ_ONCE(p->on_rq) && ttwu_runnable(p, wake_flags)) 4162 goto unlock; 4163 4164 if (READ_ONCE(p->__state) & TASK_UNINTERRUPTIBLE) 4165 trace_sched_blocked_reason(p); 4166 4167 #ifdef CONFIG_SMP 4168 /* 4169 * Ensure we load p->on_cpu _after_ p->on_rq, otherwise it would be 4170 * possible to, falsely, observe p->on_cpu == 0. 4171 * 4172 * One must be running (->on_cpu == 1) in order to remove oneself 4173 * from the runqueue. 4174 * 4175 * __schedule() (switch to task 'p') try_to_wake_up() 4176 * STORE p->on_cpu = 1 LOAD p->on_rq 4177 * UNLOCK rq->lock 4178 * 4179 * __schedule() (put 'p' to sleep) 4180 * LOCK rq->lock smp_rmb(); 4181 * smp_mb__after_spinlock(); 4182 * STORE p->on_rq = 0 LOAD p->on_cpu 4183 * 4184 * Pairs with the LOCK+smp_mb__after_spinlock() on rq->lock in 4185 * __schedule(). See the comment for smp_mb__after_spinlock(). 4186 * 4187 * Form a control-dep-acquire with p->on_rq == 0 above, to ensure 4188 * schedule()'s deactivate_task() has 'happened' and p will no longer 4189 * care about it's own p->state. See the comment in __schedule(). 4190 */ 4191 smp_acquire__after_ctrl_dep(); 4192 4193 /* 4194 * We're doing the wakeup (@success == 1), they did a dequeue (p->on_rq 4195 * == 0), which means we need to do an enqueue, change p->state to 4196 * TASK_WAKING such that we can unlock p->pi_lock before doing the 4197 * enqueue, such as ttwu_queue_wakelist(). 4198 */ 4199 WRITE_ONCE(p->__state, TASK_WAKING); 4200 4201 /* 4202 * If the owning (remote) CPU is still in the middle of schedule() with 4203 * this task as prev, considering queueing p on the remote CPUs wake_list 4204 * which potentially sends an IPI instead of spinning on p->on_cpu to 4205 * let the waker make forward progress. This is safe because IRQs are 4206 * disabled and the IPI will deliver after on_cpu is cleared. 4207 * 4208 * Ensure we load task_cpu(p) after p->on_cpu: 4209 * 4210 * set_task_cpu(p, cpu); 4211 * STORE p->cpu = @cpu 4212 * __schedule() (switch to task 'p') 4213 * LOCK rq->lock 4214 * smp_mb__after_spin_lock() smp_cond_load_acquire(&p->on_cpu) 4215 * STORE p->on_cpu = 1 LOAD p->cpu 4216 * 4217 * to ensure we observe the correct CPU on which the task is currently 4218 * scheduling. 4219 */ 4220 if (smp_load_acquire(&p->on_cpu) && 4221 ttwu_queue_wakelist(p, task_cpu(p), wake_flags)) 4222 goto unlock; 4223 4224 /* 4225 * If the owning (remote) CPU is still in the middle of schedule() with 4226 * this task as prev, wait until it's done referencing the task. 4227 * 4228 * Pairs with the smp_store_release() in finish_task(). 4229 * 4230 * This ensures that tasks getting woken will be fully ordered against 4231 * their previous state and preserve Program Order. 4232 */ 4233 smp_cond_load_acquire(&p->on_cpu, !VAL); 4234 4235 trace_android_rvh_try_to_wake_up(p); 4236 4237 cpu = select_task_rq(p, p->wake_cpu, wake_flags | WF_TTWU); 4238 if (task_cpu(p) != cpu) { 4239 if (p->in_iowait) { 4240 delayacct_blkio_end(p); 4241 atomic_dec(&task_rq(p)->nr_iowait); 4242 } 4243 4244 wake_flags |= WF_MIGRATED; 4245 psi_ttwu_dequeue(p); 4246 set_task_cpu(p, cpu); 4247 } 4248 #else 4249 cpu = task_cpu(p); 4250 #endif /* CONFIG_SMP */ 4251 4252 ttwu_queue(p, cpu, wake_flags); 4253 unlock: 4254 raw_spin_unlock_irqrestore(&p->pi_lock, flags); 4255 out: 4256 if (success) { 4257 trace_android_rvh_try_to_wake_up_success(p); 4258 ttwu_stat(p, task_cpu(p), wake_flags); 4259 } 4260 preempt_enable(); 4261 4262 return success; 4263 } 逐行解读代码并给出解释

Collecting tornado!=6.5.0,<7,>=6.0.3 (from streamlit) Downloading https://mirrors.aliyun.com/pypi/packages/7d/f7/0c48ba992d875521ac761e6e04b0a1750f8150ae42ea26df1852d6a98942/tornado-6.5.1-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (443 kB) Requirement already satisfied: jinja2 in /home/devadmin/miniconda3/envs/PDF-md/lib/python3.11/site-packages (from altair!=5.4.0,!=5.4.1,<6,>=4.0->streamlit) (3.1.6) Collecting jsonschema>=3.0 (from altair!=5.4.0,!=5.4.1,<6,>=4.0->streamlit) Downloading https://mirrors.aliyun.com/pypi/packages/fe/54/c86cd8e011fe98803d7e382fd67c0df5ceab8d2b7ad8c5a81524f791551c/jsonschema-4.25.0-py3-none-any.whl (89 kB) Collecting narwhals>=1.14.2 (from altair!=5.4.0,!=5.4.1,<6,>=4.0->streamlit) Downloading https://mirrors.aliyun.com/pypi/packages/7f/26/43caf834e47c63883a5eddc02893b7fdbe6a0a4508ff6dc401907f3cc085/narwhals-2.0.1-py3-none-any.whl (385 kB) Collecting gitdb<5,>=4.0.1 (from gitpython!=3.1.19,<4,>=3.0.7->streamlit) Downloading https://mirrors.aliyun.com/pypi/packages/a0/61/5c78b91c3143ed5c14207f463aecfc8f9dbb5092fb2869baf37c273b2705/gitdb-4.0.12-py3-none-any.whl (62 kB) Collecting smmap<6,>=3.0.1 (from gitdb<5,>=4.0.1->gitpython!=3.1.19,<4,>=3.0.7->streamlit) Downloading https://mirrors.aliyun.com/pypi/packages/04/be/d09147ad1ec7934636ad912901c5fd7667e1c858e19d355237db0d0cd5e4/smmap-5.0.2-py3-none-any.whl (24 kB) Collecting python-dateutil>=2.8.2 (from pandas<3,>=1.4.0->streamlit) Downloading https://mirrors.aliyun.com/pypi/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl (229 kB) Collecting pytz>=2020.1 (from pandas<3,>=1.4.0->streamlit) Downloading https://mirrors.aliyun.com/pypi/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl (509 kB) Collecting tzdata>=2022.7 (from pandas<3,>=1.4.0->streamlit) Downloading https://mirrors.aliyun.com/pypi/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl (347 kB) Requirement already satisfied: charset_normalizer<4,>=2 in /home/devadmin/miniconda3/envs/PDF-md/lib/python3.11/site-packages (from requests<3,>=2.27->streamlit) (3.4.2) Requirement already satisfied: idna<4,>=2.5 in /home/devadmin/miniconda3/envs/PDF-md/lib/python3.11/site-packages (from requests<3,>=2.27->streamlit) (3.10) Requirement already satisfied: urllib3<3,>=1.21.1 in /home/devadmin/miniconda3/envs/PDF-md/lib/python3.11/site-packages (from requests<3,>=2.27->streamlit) (2.5.0) Requirement already satisfied: certifi>=2017.4.17 in /home/devadmin/miniconda3/envs/PDF-md/lib/python3.11/site-packages (from requests<3,>=2.27->streamlit) (2025.8.3) Requirement already satisfied: MarkupSafe>=2.0 in /home/devadmin/miniconda3/envs/PDF-md/lib/python3.11/site-packages (from jinja2->altair!=5.4.0,!=5.4.1,<6,>=4.0->streamlit) (3.0.2) Collecting attrs>=22.2.0 (from jsonschema>=3.0->altair!=5.4.0,!=5.4.1,<6,>=4.0->streamlit) Downloading https://mirrors.aliyun.com/pypi/packages/77/06/bb80f5f86020c4551da315d78b3ab75e8228f89f0162f2c3a819e407941a/attrs-25.3.0-py3-none-any.whl (63 kB) Collecting jsonschema-specifications>=2023.03.6 (from jsonschema>=3.0->altair!=5.4.0,!=5.4.1,<6,>=4.0->streamlit) Downloading https://mirrors.aliyun.com/pypi/packages/01/0e/b27cdbaccf30b890c40ed1da9fd4a3593a5cf94dae54fb34f8a4b74fcd3f/jsonschema_specifications-2025.4.1-py3-none-any.whl (18 kB) Collecting referencing>=0.28.4 (from jsonschema>=3.0->altair!=5.4.0,!=5.4.1,<6,>=4.0->streamlit) Downloading https://mirrors.aliyun.com/pypi/packages/c1/b1/3baf80dc6d2b7bc27a95a67752d0208e410351e3feb4eb78de5f77454d8d/referencing-0.36.2-py3-none-any.whl (26 kB) Collecting rpds-py>=0.7.1 (from jsonschema>=3.0->altair!=5.4.0,!=5.4.1,<6,>=4.0->streamlit) Downloading https://mirrors.aliyun.com/pypi/packages/34/a2/004c99936997bfc644d590a9defd9e9c93f8286568f9c16cdaf3e14429a7/rpds_py-0.26.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (383 kB) Requirement already satisfied: six>=1.5 in /home/devadmin/miniconda3/envs/PDF-md/lib/python3.11/site-packages (from python-dateutil>=2.8.2->pandas<3,>=1.4.0->streamlit) (1.17.0) Building wheels for collected packages: pyarrow Building wheel for pyarrow (pyproject.toml) ... error error: subprocess-exited-with-error × Building wheel for pyarrow (pyproject.toml) did not run successfully. │ exit code: 1 ╰─> [876 lines of output] /tmp/pip-build-env-cwl6bk4x/overlay/lib/python3.11/site-packages/setuptools/config/_apply_pyprojecttoml.py:82: SetuptoolsDeprecationWarning: project.license as a TOML table is deprecated !! ******************************************************************************** Please use a simple string containing a SPDX expression for project.license. You can also use project.license-files. (Both options available on setuptools>=77.0.0). By 2026-Feb-18, you need to update your project and remove deprecated calls or your builds will no longer be supported. See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! corresp(dist, value, root_dir) /tmp/pip-build-env-cwl6bk4x/overlay/lib/python3.11/site-packages/setuptools/config/_apply_pyprojecttoml.py:61: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: Apache Software License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! dist._finalize_license_expression() /tmp/pip-build-env-cwl6bk4x/overlay/lib/python3.11/site-packages/setuptools/dist.py:483: SetuptoolsDeprecationWarning: Pattern '../LICENSE.txt' cannot contain '..' !! ******************************************************************************** Please ensure the files specified are contained by the root of the Python package (normally marked by pyproject.toml). By 2026-Mar-20, you need to update your project and remove deprecated calls or your builds will no longer be supported. See https://packaging.python.org/en/latest/specifications/glob-patterns/ for details. ******************************************************************************** !! for path in sorted(cls._find_pattern(pattern, enforce_match)) /tmp/pip-build-env-cwl6bk4x/overlay/lib/python3.11/site-packages/setuptools/dist.py:483: SetuptoolsDeprecationWarning: Cannot find any files for the given pattern. !! ******************************************************************************** Pattern '../LICENSE.txt' did not match any files. By 2026-Mar-20, you need to update your project and remove deprecated calls or your builds will no longer be supported. ******************************************************************************** !! for path in sorted(cls._find_pattern(pattern, enforce_match)) /tmp/pip-build-env-cwl6bk4x/overlay/lib/python3.11/site-packages/setuptools/dist.py:483: SetuptoolsD

-- ROMFS: Adding boards/px4/fmu-v5/extras/px4_io-v2_default.bin -> /etc/extras/px4_io-v2_default.bin -- Configuring done -- Generating done -- Build files have been written to: /home/me/下载/px4-autopilot-1.15.4/build/px4_fmu-v5_default [1/1299] Generating git version header FAILED: src/lib/version/build_git_version.h cd /home/me/下载/px4-autopilot-1.15.4 && /usr/bin/python3 /home/me/下载/px4-autopilot-1.15.4/src/lib/version/px_update_git_header.py /home/me/下载/px4-autopilot-1.15.4/build/px4_fmu-v5_default/src/lib/version/build_git_version.h --validate Error: the git tag 'c49f4c2142' does not match the expected format. The expected format is 'v[-<custom version>]' : v<major>.<minor>.[-rc<rc>|-beta<beta>|-alpha<alpha>|-dev] <custom version>: <major>.<minor>.[-rc<rc>|-beta<beta>|-alpha<alpha>|-dev] Examples: v1.9.0-rc3 (preferred) v1.9.0-beta1 v1.9.0-1.0.0 v1.9.0-1.0.0-alpha2 See also https://docs.px4.io/main/en/dev_setup/building_px4.html#building-for-nuttx [2/1299] Generating ../../../platforms/nuttx/NuttX/nuttx/.config ninja: build stopped: subcommand failed. make: *** [Makefile:227:px4_fmu-v5_default] 错误 1如何修改代码避免此错误############################################################################ # # Copyright (c) 2017 - 2024 PX4 Development Team. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # 3. Neither the name PX4 nor the names of its contributors may be # used to endorse or promote products derived from this software # without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # ############################################################################ #============================================================================= # CMAKE CODING STANDARD FOR PX4 # # Structure # --------------------------------------------------------------------------- # # * Common functions should be included in px_base.cmake. # # * OS/ board specific fucntions should be include in # px_impl_${PX4_PLATFORM}.cmake # # Formatting # --------------------------------------------------------------------------- # # * Use hard indents to match the px4 source code. # # * All function and script arguments are upper case. # # * All local variables are lower case. # # * All cmake functions are lowercase. # # * For else, endif, endfunction, etc, never put the name of the statement # # Functions/Macros # --------------------------------------------------------------------------- # # * Use px4_parse_function_args to parse functions and check for required # arguments. Unless there is only one argument in the function and it is clear. # # * Never use macros. They allow overwriting global variables and this # makes variable declarations hard to locate. # # * If a target from add_custom_* is set in a function, explicitly pass it # as an output argument so that the target name is clear to the user. # # * Avoid use of global variables in functions. Functions in a nested # scope may use global variables, but this makes it difficult to # reuse functions. # # Included CMake Files # --------------------------------------------------------------------------- # # * All variables in config files must have the prefix "config_". # # * Never set global variables in an included cmake file, # you may only define functions. This excludes config and Toolchain files. # This makes it clear to the user when variables are being set or targets # are being created. # # * Setting a global variable in a CMakeLists.txt file is ok, because # each CMakeLists.txt file has scope in the current directory and all # subdirectories, so it is not truly global. # # * All toolchain files should be included in the cmake # directory and named Toolchain-"name".cmake. # # Misc # --------------------------------------------------------------------------- # # * If referencing a string variable, don't put it in quotes. # Don't do "${PX4_PLATFORM}" STREQUAL "posix", # instead type ${PX4_PLATFORM} STREQUAL "posix". This will throw an # error when ${PX4_PLATFORM} is not defined instead of silently # evaluating to false. # #============================================================================= cmake_minimum_required(VERSION 3.9 FATAL_ERROR) set(PX4_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE FILEPATH "PX4 source directory" FORCE) set(PX4_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE FILEPATH "PX4 binary directory" FORCE) list(APPEND CMAKE_MODULE_PATH ${PX4_SOURCE_DIR}/cmake) include(px4_parse_function_args) #============================================================================= # git # include(px4_git) execute_process( COMMAND git describe --exclude ext/* --always --tags OUTPUT_VARIABLE PX4_GIT_TAG OUTPUT_STRIP_TRAILING_WHITESPACE WORKING_DIRECTORY ${PX4_SOURCE_DIR} ) set(PX4_GIT_TAG "v1.15.4") # git describe to X.Y.Z version string(REPLACE "." ";" VERSION_LIST ${PX4_GIT_TAG}) # major version list(GET VERSION_LIST 0 PX4_VERSION_MAJOR) string(REPLACE "v" "" PX4_VERSION_MAJOR ${PX4_VERSION_MAJOR}) # minor version list(GET VERSION_LIST 1 PX4_VERSION_MINOR) # patch version list(GET VERSION_LIST 2 PX4_VERSION_PATCH) string(REPLACE "-" ";" PX4_VERSION_PATCH ${PX4_VERSION_PATCH}) list(GET PX4_VERSION_PATCH 0 PX4_VERSION_PATCH) # # Capture only the hash part after 'g' string(REGEX MATCH "g([a-f0-9]+)$" GIT_HASH "${PX4_GIT_TAG}") set(PX4_GIT_HASH ${CMAKE_MATCH_1}) define_property(GLOBAL PROPERTY PX4_MODULE_LIBRARIES BRIEF_DOCS "PX4 module libs" FULL_DOCS "List of all PX4 module libraries" ) define_property(GLOBAL PROPERTY PX4_KERNEL_MODULE_LIBRARIES BRIEF_DOCS "PX4 kernel side module libs" FULL_DOCS "List of all PX4 kernel module libraries" ) define_property(GLOBAL PROPERTY PX4_MODULE_PATHS BRIEF_DOCS "PX4 module paths" FULL_DOCS "List of paths to all PX4 modules" ) define_property(GLOBAL PROPERTY PX4_SRC_FILES BRIEF_DOCS "src files from all PX4 modules & libs" FULL_DOCS "SRC files from px4_add_{module,library}" ) #============================================================================= # configuration # include(px4_add_module) set(config_module_list) set(config_kernel_list) # Find Python find_package(PythonInterp 3) # We have a custom error message to tell users how to install python3. if(NOT PYTHONINTERP_FOUND) message(FATAL_ERROR "Python 3 not found. Please install Python 3:\n" " Ubuntu: sudo apt install python3 python3-dev python3-pip\n" " macOS: brew install python") endif() option(PYTHON_COVERAGE "Python code coverage" OFF) if(PYTHON_COVERAGE) message(STATUS "python coverage enabled") set(PYTHON_EXECUTABLE coverage run -p) endif() include(px4_config) include(kconfig) message(STATUS "PX4 config: ${PX4_CONFIG}") message(STATUS "PX4 platform: ${PX4_PLATFORM}") if($ENV{CLION_IDE}) # CLion automatically executes some compiler commands after configuring the # project. This would fail on NuttX, as visibility.h tries to (indirectly) # include nuttx/config.h, which at that point does not exist yet add_definitions(-DPX4_DISABLE_GCC_POISON) endif() if(${PX4_PLATFORM} STREQUAL "posix") if(ENABLE_LOCKSTEP_SCHEDULER) add_definitions(-DENABLE_LOCKSTEP_SCHEDULER) message(STATUS "PX4 lockstep: enabled") else() message(STATUS "PX4 lockstep: disabled") endif() endif() # external modules set(EXTERNAL_MODULES_LOCATION "" CACHE STRING "External modules source location") if(NOT EXTERNAL_MODULES_LOCATION STREQUAL "") get_filename_component(EXTERNAL_MODULES_LOCATION "${EXTERNAL_MODULES_LOCATION}" ABSOLUTE) endif() set_property(GLOBAL PROPERTY PX4_MODULE_CONFIG_FILES) include(platforms/${PX4_PLATFORM}/cmake/px4_impl_os.cmake) list(APPEND CMAKE_MODULE_PATH ${PX4_SOURCE_DIR}/platforms/${PX4_PLATFORM}/cmake) if(EXISTS "${PX4_SOURCE_DIR}/platforms/${PX4_PLATFORM}/cmake/init.cmake") include(init) endif() #============================================================================= # project definition # project(px4 CXX C ASM) # CMake build type (Debug Release RelWithDebInfo MinSizeRel Coverage) if(NOT CMAKE_BUILD_TYPE) if(${PX4_PLATFORM} STREQUAL "nuttx") set(PX4_BUILD_TYPE "MinSizeRel") else() set(PX4_BUILD_TYPE "RelWithDebInfo") endif() set(CMAKE_BUILD_TYPE ${PX4_BUILD_TYPE} CACHE STRING "Build type" FORCE) endif() if((CMAKE_BUILD_TYPE STREQUAL "Debug") OR (CMAKE_BUILD_TYPE STREQUAL "Coverage")) set(MAX_CUSTOM_OPT_LEVEL -O0) elseif(CMAKE_BUILD_TYPE MATCHES "Sanitizer") set(MAX_CUSTOM_OPT_LEVEL -O1) elseif(CMAKE_BUILD_TYPE MATCHES "Release") set(MAX_CUSTOM_OPT_LEVEL -O3) else() if(px4_constrained_flash_build) set(MAX_CUSTOM_OPT_LEVEL -Os) else() set(MAX_CUSTOM_OPT_LEVEL -O2) endif() endif() set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release;RelWithDebInfo;MinSizeRel;Coverage;AddressSanitizer;UndefinedBehaviorSanitizer") message(STATUS "cmake build type: ${CMAKE_BUILD_TYPE}") # Check if LTO option and check if toolchain supports it if(LTO) include(CheckIPOSupported) check_ipo_supported() message(AUTHOR_WARNING "LTO enabled: LTO is highly experimental and should not be used in production") set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) endif() set(package-contact "[email protected]") set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PX4_BINARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PX4_BINARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PX4_BINARY_DIR}) #============================================================================= # gold linker - use if available (posix only for now) if(${PX4_PLATFORM} STREQUAL "posix") include(CMakeDependentOption) CMAKE_DEPENDENT_OPTION(USE_LD_GOLD "Use GNU gold linker" ON "NOT WIN32;NOT APPLE" OFF ) if(USE_LD_GOLD) execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE LD_VERSION) if("${LD_VERSION}" MATCHES "GNU gold") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=gold") else() set(USE_LD_GOLD OFF) endif() endif() endif() #============================================================================= # Setup install paths if(${PX4_PLATFORM} STREQUAL "posix") # This makes it possible to dynamically load code which depends on symbols # inside the px4 executable. set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_ENABLE_EXPORTS ON) if(CMAKE_BUILD_TYPE MATCHES "Coverage") include(coverage) endif() include(sanitizers) # Define GNU standard installation directories include(GNUInstallDirs) if (NOT CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Install path prefix" FORCE) endif() endif() include(ccache) #============================================================================= # get chip and chip manufacturer # px4_os_determine_build_chip() if(NOT PX4_CHIP_MANUFACTURER) message(FATAL_ERROR "px4_os_determine_build_chip() needs to set PX4_CHIP_MANUFACTURER") endif() if(NOT PX4_CHIP) message(FATAL_ERROR "px4_os_determine_build_chip() needs to set PX4_CHIP") endif() #============================================================================= # build flags # include(px4_add_common_flags) px4_add_common_flags() px4_os_add_flags() #============================================================================= # board cmake init (optional) # if(EXISTS ${PX4_BOARD_DIR}/cmake/init.cmake) include(${PX4_BOARD_DIR}/cmake/init.cmake) endif() #============================================================================= # message, and airframe generation # include(px4_metadata) add_subdirectory(msg EXCLUDE_FROM_ALL) px4_generate_airframes_xml(BOARD ${PX4_BOARD}) #============================================================================= # external projects # set(ep_base ${PX4_BINARY_DIR}/external) set_property(DIRECTORY PROPERTY EP_BASE ${ep_base}) # add external project install folders to build # add the directories so cmake won't warn execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${ep_base}) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${ep_base}/Install) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${ep_base}/Install/lib) link_directories(${ep_base}/Install/lib) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${ep_base}/Install/include) include_directories(${ep_base}/Install/include) #============================================================================= # external modules # set(external_module_paths) if (NOT EXTERNAL_MODULES_LOCATION STREQUAL "") message(STATUS "External modules: ${EXTERNAL_MODULES_LOCATION}") add_subdirectory("${EXTERNAL_MODULES_LOCATION}/src" external_modules) foreach(external_module ${config_module_list_external}) add_subdirectory(${EXTERNAL_MODULES_LOCATION}/src/${external_module} external_modules/${external_module}) list(APPEND external_module_paths ${EXTERNAL_MODULES_LOCATION}/src/${external_module}) endforeach() endif() #============================================================================= # Testing - Automatic unit and integration testing with CTest # # optionally enable cmake testing (supported only on posix) option(CMAKE_TESTING "Configure test targets" OFF) if(${PX4_CONFIG} STREQUAL "px4_sitl_test") set(CMAKE_TESTING ON) endif() if(CMAKE_TESTING) include(CTest) # sets BUILD_TESTING variable endif() # enable test filtering to run only specific tests with the ctest -R regex functionality set(TESTFILTER "" CACHE STRING "Filter string for ctest to selectively only run specific tests (ctest -R)") # if testing is enabled download and configure gtest list(APPEND CMAKE_MODULE_PATH ${PX4_SOURCE_DIR}/cmake/gtest/) include(px4_add_gtest) if(BUILD_TESTING) include(gtest) add_custom_target(test_results COMMAND GTEST_COLOR=1 ${CMAKE_CTEST_COMMAND} --output-on-failure -T Test -R ${TESTFILTER} USES_TERMINAL DEPENDS px4 examples__dyn_hello USES_TERMINAL COMMENT "Running tests" WORKING_DIRECTORY ${PX4_BINARY_DIR}) set_target_properties(test_results PROPERTIES EXCLUDE_FROM_ALL TRUE) endif() #============================================================================= # subdirectories # add_library(parameters_interface INTERFACE) add_library(kernel_parameters_interface INTERFACE) add_library(events_interface INTERFACE) add_library(kernel_events_interface INTERFACE) include(px4_add_library) add_subdirectory(src/lib EXCLUDE_FROM_ALL) add_subdirectory(platforms/${PX4_PLATFORM}/src/px4) add_subdirectory(platforms EXCLUDE_FROM_ALL) if(EXISTS "${PX4_BOARD_DIR}/CMakeLists.txt") add_subdirectory(${PX4_BOARD_DIR}) endif() foreach(module ${config_module_list}) add_subdirectory(src/${module}) endforeach() # add events lib after modules and libs as it needs to know all source files (PX4_SRC_FILES) add_subdirectory(src/lib/events EXCLUDE_FROM_ALL) # metadata needs PX4_MODULE_CONFIG_FILES add_subdirectory(src/lib/metadata EXCLUDE_FROM_ALL) # must be the last module before firmware add_subdirectory(src/lib/parameters EXCLUDE_FROM_ALL) if(${PX4_PLATFORM} STREQUAL "nuttx" AND NOT CONFIG_BUILD_FLAT) target_link_libraries(parameters_interface INTERFACE usr_parameters) target_link_libraries(kernel_parameters_interface INTERFACE parameters) target_link_libraries(events_interface INTERFACE usr_events) target_link_libraries(kernel_events_interface INTERFACE events) else() target_link_libraries(parameters_interface INTERFACE parameters) target_link_libraries(events_interface INTERFACE events) endif() # firmware added last to generate the builtin for included modules add_subdirectory(platforms/${PX4_PLATFORM}) #============================================================================= # uORB graph generation: add a custom target 'uorb_graph' # set(uorb_graph_config ${PX4_BOARD}) set(graph_module_list "") foreach(module ${config_module_list}) set(graph_module_list "${graph_module_list}" "--src-path" "src/${module}") endforeach() add_custom_command(OUTPUT ${uorb_graph_config} COMMAND ${PYTHON_EXECUTABLE} ${PX4_SOURCE_DIR}/Tools/uorb_graph/create.py ${graph_module_list} --src-path src/lib --merge-depends --exclude-path src/examples --exclude-path src/lib/parameters # FIXME: enable & fix --file ${PX4_SOURCE_DIR}/Tools/uorb_graph/graph_${uorb_graph_config} WORKING_DIRECTORY ${PX4_SOURCE_DIR} COMMENT "Generating uORB graph" ) add_custom_target(uorb_graph DEPENDS ${uorb_graph_config}) include(bloaty) include(doxygen) include(metadata) include(package) # install python requirements using configured python add_custom_target(install_python_requirements COMMAND ${PYTHON_EXECUTABLE} -m pip install --break-system-packages --requirement ${PX4_SOURCE_DIR}/Tools/setup/requirements.txt DEPENDS ${PX4_SOURCE_DIR}/Tools/setup/requirements.txt USES_TERMINAL ) if(EXISTS "${PX4_SOURCE_DIR}/platforms/${PX4_PLATFORM}/cmake/finalize.cmake") include(finalize) endif()

【SLP·Python】基于 DTW GMM HMM 三种方法实现的语音分类识别系统 Sherry-XLL 于 2021-08-28 17:27:16 发布 阅读量8.9k 收藏 133 点赞数 22 文章标签: python 语音识别 hmm 机器学习 版权 CSDN学习社区 文章已被社区收录 加入社区 本文探讨了在孤立词语音识别中,使用动态时间规整(DTW)、高斯混合模型(GMM)和隐马尔可夫模型(HMM)的方法。通过Python实现,针对10个数字的语音识别任务,对数据集进行预处理、特征提取,训练模型并进行预测。实验结果显示,自定义GMM模型达到了100%的准确率,而DTW和HMM模型则分别达到78%和87.5%。此外,文章提供了相关代码和数据集链接,供读者参考和复现实验结果。 摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 > 展开 前言 Github 项目地址:https://github.com/Sherry-XLL/Digital-Recognition-DTW_HMM_GMM 在孤立词语音识别(Isolated Word Speech Recognition) 中,DTW,GMM 和 HMM 是三种典型的方法: 动态时间规整(DTW, Dyanmic Time Warping) 高斯混合模型(GMM, Gaussian Mixed Model) 隐马尔可夫模型(HMM, Hidden Markov Model) 本文并不介绍这三种方法的基本原理,而是侧重于 Python 版代码的实现,针对一个具体的语音识别任务——10 digits recognition system,分别使用 DTW、GMM 和 HMM 建立对 0~9 十个数字的孤立词语音分类识别模型。 前言 一、音频数据处理 1. 数据集 2. 音频预处理 3. MFCC 特征提取 二、Isolated Speech Recognition - DTW 1. DTW 算法步骤 2. DTW 函数编写 3. 模型训练与预测 三、Isolated Speech Recognition - GMM 1. GMM 模型训练流程 2. EM 算法步骤 3. GMM 实现代码 四、Isolated Speech Recognition - HMM 1. 隐马尔可夫模型 2. 代码实现 五、实验结果 1. 实验环境 2. 文件简介 3. 结果对比 六、参考链接 一、音频数据处理 1. 数据集 本文中的语音识别任务是对 0 ~ 9 这十个建立孤立词语言识别模型,所使用的数据集类似于语音版的 MNIST 手写数字数据库。原始数据集是 20 个人录制的数字 0 ~ 9 的音频文件,共 200 条 .wav 格式的录音,同样上传到了 Github 项目 中,分支情况如下: records digit_0 digit_1 digit_2 digit_3 digit_4 digit_5 digit_6 digit_7 digit_8 digit_9 1_0.wav ...... 20_0.wav records 文件夹下包括 digit_0 ~ digit_9 十个子文件夹。每个子文件夹代表一个数字,里面有 20 个人对该数字的录音音频,1_0.wav 就代表第 1 个人录数字 0 的音频文件。 为了比较不同方法的性能,我们将数据集按照 4:1 的比例分为训练集和测试集。我们更想了解的是模型在未知数据上的表现,于是前16个人的数据都被划分为了训练集,共 160 条音频文件;17-20 这四个人的音频为测试集,共 40 条 .wav 格式的录音。 2. 音频预处理 preprocess.py referencing https://github.com/rocketeerli/Computer-VisionandAudio-Lab/tree/master/lab1 当录数字的音频时,录音前后会有微小时间的空隙,并且每段音频的空白片段长度不一。如果忽略这个差异,直接对原音频进行建模运算,结果难免会受到影响,因此本文选择基于双阈值的语音端点检测对音频进行预处理。 对于每段 .wav 音频,首先用 wave 读取,并通过 np.frombuffer 和 readframes 得到二进制数组。然后,编写计算能量 (energy) 的函数 calEnergy 和计算过零率 (zero-crossing rate,ZCR) 的函数 calZeroCrossingRate,帧长 framesize 设置为常用的 256: def calEnergy(wave_data): """ :param wave_data: binary data of audio file :return: energy """ energy = [] sum = 0 for i in range(len(wave_data)): sum = sum + (int(wave_data[i]) * int(wave_data[i])) if (i + 1) % 256 == 0: energy.append(sum) sum = 0 elif i == len(wave_data) - 1: energy.append(sum) return energy def calZeroCrossingRate(wave_data): """ :param wave_data: binary data of audio file :return: ZeroCrossingRate """ zeroCrossingRate = [] sum = 0 for i in range(len(wave_data)): sum = sum + np.abs(int(wave_data[i] >= 0) - int(wave_data[i - 1] >= 0)) if (i + 1) % 256 == 0: zeroCrossingRate.append(float(sum) / 255) sum = 0 elif i == len(wave_data) - 1: zeroCrossingRate.append(float(sum) / 255) return zeroCrossingRate 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 代入音频的二进制数据得到能量和过零率数组之后,通过语音端点检测得到处理之后的音频数据,端点检测函数 endPointDetect 主要为三个步骤: 先根据 energy 和 zeroCrossingRate 计算高能阈值 (high energy threshold, MH) 第一步是计算较高的短时能量作为高能阈值 (high energy threshold, MH),可用于识别语音的浊音部分,得到初步检测数据 A。 第二步是计算较低的能量阈值 (low energy threshold, ML),使用该阈值搜索两端,第二次检测从 A 得到 B。 第三步是计算过零率阈值 (zero crossing rate threshold, Zs),在考虑过零率的基础上进一步处理第二步的结果 B,返回处理好的数据 C。 最后,将编号 1-16 被试者的音频文件存入 processed_train_records ,编号 17-20 存入 processed_test_records。 3. MFCC 特征提取 音频文件无法直接进行语音识别,需要对其进行特征提取。在语音识别(Speech Recognition)领域,最常用到的语音特征就是梅尔倒谱系数(Mel-scale Frequency Cepstral Coefficients,MFCC)。 在 Python 中,可以用封装好的工具包 librosa 或 python_speech_features 实现对 MFCC 特征的提取。本文使用 librosa 提取给定音频的 MFCC 特征,每帧提取 39 维 MFCC 特征: import librosa def mfcc(wav_path, delta = 2): """ Read .wav files and calculate MFCC :param wav_path: path of audio file :param delta: derivative order, default order is 2 :return: mfcc """ y, sr = librosa.load(wav_path) # MEL frequency cepstrum coefficient mfcc_feat = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13) ans = [mfcc_feat] # Calculate the 1st derivative if delta >= 1: mfcc_delta1 = librosa.feature.delta(mfcc_feat, order=1, mode ='nearest') ans.append(mfcc_delta1) # Calculate the 2nd derivative if delta >= 2: mfcc_delta2 = librosa.feature.delta(mfcc_feat, order=2, mode ='nearest') ans.append(mfcc_delta2) return np.transpose(np.concatenate(ans, axis=0), [1,0]) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 可以参考官网 librosa 和 python-speech-features 了解更多音频特征提取工具。 二、Isolated Speech Recognition - DTW 1. DTW 算法步骤 动态时间规整(DTW, Dyanmic Time Warping) 本质上是一种简单的动态规划算法,它可以分为两个步骤,一个是计算两种模式的帧之间的距离,即得到帧匹配距离矩阵;另一个是在帧匹配距离矩阵中找到最优路径。算法步骤如下: 首先,使用欧几里德距离 (Euclidean distance) 初始化成本矩阵 (cost matrix)。 其次,使用动态规划计算成本矩阵,将每个数据的向量与模板向量进行比较,动态转移方程为 c o s t [ i , j ] + = m i n ( [ c o s t [ i , j ] , c o s t [ i + 1 , j ] , c o s t [ i , j + 1 ] ] ) . cost[i, j] += min([cost[i, j], cost[i+1, j], cost[i, j+1]]). cost[i,j]+=min([cost[i,j],cost[i+1,j],cost[i,j+1]]). 第三,计算规整路径 (warp path),最小距离为标准化距离。将第一个训练序列设置为标准 (template),合并所有训练序列并求其平均值,返回 0-9 位数字的模型。 测试过程中,使用 DTW 衡量每条音频到 0-9 这十个模板的”距离“,并选择模板距离最小的数字作为音频的预测值。 2. DTW 函数编写 编写 dtw 函数的关键在于两段 MFCC 序列的动态规划矩阵和规整路径的计算。令输入的两段 MFCC 序列分别为 M1 和 M2,M1_len 和 M2_len 表示各自的长度,则 cost matrix 的大小为 M1_len * M2_len,先用欧式距离对其进行初始化,再根据转移式计算 cost matrix: def dtw(M1, M2): """ Compute Dynamic Time Warping(DTW) of two mfcc sequences. :param M1, M2: two mfcc sequences :return: the minimum distance and the wrap path """ # length of two sequences M1_len = len(M1) M2_len = len(M2) cost_0 = np.zeros((M1_len + 1, M2_len + 1)) cost_0[0, 1:] = np.inf cost_0[1:, 0] = np.inf # Initialize the array size to M1_len * M2_len cost = cost_0[1:, 1:] for i in range(M1_len): for j in range(M2_len): cost[i, j] = calEuclidDist(M1[i], M2[j]) # dynamic programming to calculate cost matrix for i in range(M1_len): for j in range(M2_len): cost[i, j] += min([cost_0[i, j], \ cost_0[min(i + 1, M1_len - 1), j], \ cost_0[i, min(j + 1, M2_len - 1)]]) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 欧式距离的计算函数 calEuclidDist 可以用一行代码完成: def calEuclidDist(A, B): """ :param A, B: two vectors :return: the Euclidean distance of A and B """ return sqrt(sum([(a - b) ** 2 for (a, b) in zip(A, B)])) 1 2 3 4 5 6 cost matrix 计算完成后还需计算 warp path,MFCC 序列长度为 1 时的路径可以单独分情况讨论,最小代价的 path_1 和 path_2 即为所求,最后返回数组 path: # calculate the warp path if len(M1) == 1: path = np.zeros(len(M2)), range(len(M2)) elif len(M2) == 1: path = range(len(M1)), np.zeros(len(M1)) else: i, j = np.array(cost_0.shape) - 2 path_1, path_2 = [i], [j] # path_1, path_2 with the minimum cost is what we want while (i > 0) or (j > 0): arg_min = np.argmin((cost_0[i, j], cost_0[i, j + 1], cost_0[i + 1, j])) if arg_min == 0: i -= 1 j -= 1 elif arg_min == 1: i -= 1 else: j -= 1 path_1.insert(0, i) path_2.insert(0, j) # convert to array path = np.array(path_1), np.array(path_2) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 3. 模型训练与预测 在模型训练阶段,对于每个数字的 16 条音频文件,现计算 MFCC 序列到 mfcc_list 列表中,将第一个音频文件的 MFCC 序列设置为标准,计算标准模板和每条模板之间的动态时间规整路径,再对其求平均进行归一化,将结果 append 到 model 列表中。返回的 model 包含 0-9 这 10 个数字的 DTW 模型: # set the first sequence as standard, merge all training sequences mfcc_count = np.zeros(len(mfcc_list[0])) mfcc_all = np.zeros(mfcc_list[0].shape) for i in range(len(mfcc_list)): # calculate the wrap path between standard and each template _, path = dtw(mfcc_list[0], mfcc_list[i]) for j in range(len(path[0])): mfcc_count[int(path[0][j])] += 1 mfcc_all[int(path[0][j])] += mfcc_list[i][path[1][j]] # Generalization by averaging the templates model_digit = np.zeros(mfcc_all.shape) for i in range(len(mfcc_count)): for j in range(len(mfcc_all[i])): model_digit[i][j] = mfcc_all[i][j] / mfcc_count[i] # return model with models of 0-9 digits model.append(model_digit) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 测试阶段比较简单,将训练得到的 model 和需要预测音频的路径输入到函数 predict_dtw 中,分别计算 model 中每位数字到音频 MFCC 序列的最短距离 min_dist,min_dist 所对应的数字即为该音频的预测标签。 def predict_dtw(model, file_path): """ :param model: trained model :param file_path: path of .wav file :return: digit """ # Iterate, find the digit with the minimum distance digit = 0 min_dist, _ = dtw(model[0], mfcc_feat) for i in range(1, len(model)): dist, _ = dtw(model[i], mfcc_feat) if dist < min_dist: digit = i min_dist = dist return str(digit) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 三、Isolated Speech Recognition - GMM 1. GMM 模型训练流程 参考 sklearn 高斯混合模型中文文档:https://www.scikitlearn.com.cn/0.21.3/20/#211 高斯混合模型(GMM, Gaussian Mixed Model) 是一个假设所有的数据点都是生成于有限个带有未知参数的高斯分布所混合的概率模型,包含了数据的协方差结构以及隐高斯模型的中心信息,同样可以用于解决本文的数字识别任务。 scikit-learn 是基于 Python 语言的机器学习工具,sklearn.mixture 是其中应用高斯混合模型进行非监督学习的包,GaussianMixture 对象实现了用来拟合高斯混合模型的期望最大化 (EM, Expectation-Maximum) 算法。 如果想要直接调用封装好的库,只需在代码中加入 from sklearn.mixture import GaussianMixture,GaussianMixture.fit 便可以从训练数据中拟合出一个高斯混合模型,并用 predict 进行预测,详情参见官方文档。 GMM 模型的训练和预测过程与 DTW 类似,此处不再赘述,流程图如下所示: 2. EM 算法步骤 参考文档:https://blog.csdn.net/nsh119/article/details/79584629?spm=1001.2014.3001.5501 GMM 模型的核心在于期望最大化 (EM, Expectation-Maximum) 算法,模型参数的训练步骤主要为 Expectation 的 E 步和 Maximum 的 M 步: (1) 取参数的初始值开始迭代。 (2) E 步:依据当前模型参数,计算分模型 k kk 对观测数据 y j y_jy j ​ 的相应度 γ ^ j k = α j ϕ ( y j ∣ θ k ) Σ k = 1 K α k ϕ ( y j ∣ θ k ) , j = 1 , 2 , . . . , N ; k = 1 , 2 , . . . , K \hat{\gamma}_{jk}=\dfrac{\alpha_j\phi(y_j|\theta_k)}{\Sigma^K_{k=1}\alpha_k\phi(y_j|\theta_k)},j=1,2,...,N; k=1,2,...,K γ ^ ​ jk ​ = Σ k=1 K ​ α k ​ ϕ(y j ​ ∣θ k ​ ) α j ​ ϕ(y j ​ ∣θ k ​ ) ​ ,j=1,2,...,N;k=1,2,...,K (3) M 步:计算新一轮迭代的模型参数 μ ^ k = Σ j = 1 N γ ^ j k y j Σ j = 1 N γ ^ j k , k = 1 , 2 , . . . , K σ ^ k 2 = Σ j = 1 N γ ^ j k ( y j − μ k ) 2 Σ j = 1 N γ ^ j k , k = 1 , 2 , . . . , K α ^ k = Σ j = 1 N γ ^ j k N , k = 1 , 2 , . . . , K μ^kσ^2kα^k=ΣNj=1γ^jkyjΣNj=1γ^jk,k=1,2,...,K=ΣNj=1γ^jk(yj−μk)2ΣNj=1γ^jk,k=1,2,...,K=ΣNj=1γ^jkN,k=1,2,...,K 𝜇 ^ 𝑘 = Σ 𝑗 = 1 𝑁 𝛾 ^ 𝑗 𝑘 𝑦 𝑗 Σ 𝑗 = 1 𝑁 𝛾 ^ 𝑗 𝑘 , 𝑘 = 1 , 2 , . . . , 𝐾 𝜎 ^ 𝑘 2 = Σ 𝑗 = 1 𝑁 𝛾 ^ 𝑗 𝑘 ( 𝑦 𝑗 − 𝜇 𝑘 ) 2 Σ 𝑗 = 1 𝑁 𝛾 ^ 𝑗 𝑘 , 𝑘 = 1 , 2 , . . . , 𝐾 𝛼 ^ 𝑘 = Σ 𝑗 = 1 𝑁 𝛾 ^ 𝑗 𝑘 𝑁 , 𝑘 = 1 , 2 , . . . , 𝐾 μ ^ ​ k ​ σ ^ k 2 ​ α ^ k ​ ​ = Σ j=1 N ​ γ ^ ​ jk ​ Σ j=1 N ​ γ ^ ​ jk ​ y j ​ ​ ,k=1,2,...,K = Σ j=1 N ​ γ ^ ​ jk ​ Σ j=1 N ​ γ ^ ​ jk ​ (y j ​ −μ k ​ ) 2 ​ ,k=1,2,...,K = N Σ j=1 N ​ γ ^ ​ jk ​ ​ ,k=1,2,...,K ​ 3. GMM 实现代码 sklearn.mixture/_gaussian_mixture.py:https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/mixture/_gaussian_mixture.py GMM 模型实现可以参考 GaussianMixture 的源码,本文对 sklearn 的实现方式进行了简化,关键在于 GMM 这个类的函数实现。 我们实现的 GMM 类包含三个参数 (parameter) 和三个属性 (attribute):n_components 表示模型中状态的数目;mfcc_data 为音频提取的 MFCC 数据;random_state 是控制随机数的参数;means 表示在每个状态中 mixture component 的平均值;var 为方差;weights 是每个 component 的参数矩阵。 class GMM: """Gaussian Mixture Model. Parameters ---------- n_components : int Number of states in the model. mfcc_data : array, shape (, 39) Mfcc data of training wavs. random_state: int RandomState instance or None, optional (default=0) Attributes ---------- means : array, shape (n_components, 1) Mean parameters for each mixture component in each state. var : array, shape (n_components, 1) Variance parameters for each mixture component in each state. weights : array, shape (1, n_components) Weights matrix of each component. """ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 根据均值和方差可以计算对数高斯概率: def log_gaussian_prob(x, means, var): """ Estimate the log Gaussian probability :param x: input array :param means: The mean of each mixture component. :param var: The variance of each mixture component. :return: the log Gaussian probability """ return (-0.5 * np.log(var) - np.divide(np.square(x - means), 2 * var) - 0.5 * np.log(2 * np.pi)).sum() 1 2 3 4 5 6 7 8 9 GMM 类中包含五个部分:__init__ 用于初始化;e_step 是 Expectation 步骤;m_step 是 Maximization 步骤;train 用于调用 E 步和 M 步进行参数训练;log_prob 计算每个高斯模型的对数高斯概率。 def __init__(self, mfcc_data, n_components, random_state=0): # Initialization self.mfcc_data = mfcc_data self.means = np.tile(np.mean(self.mfcc_data, axis=0), (n_components, 1)) # randomization np.random.seed(random_state) for k in range(n_components): randn_k = np.random.randn() self.means[k] += 0.01 * randn_k * np.sqrt(np.var(self.mfcc_data, axis=0)) self.var = np.tile(np.var(self.mfcc_data, axis=0), (n_components, 1)) self.weights = np.ones(n_components) / n_components self.n_components = n_components def e_step(self, x): """ Expectation-step. :param x: input array-like data :return: Logarithm of the posterior probabilities (or responsibilities) of the point of each sample in x. """ log_resp = np.zeros((x.shape[0], self.n_components)) for i in range(x.shape[0]): log_resp_i = np.log(self.weights) for j in range(self.n_components): log_resp_i[j] += log_gaussian_prob(x[i], self.means[j], self.var[j]) y = np.exp(log_resp_i - log_resp_i.max()) log_resp[i] = y / y.sum() return log_resp def m_step(self, x, log_resp): """ Maximization step. :param x: input array-like data :param log_resp: Logarithm of the posterior probabilities (or responsibilities) of the point of each sample in data """ self.weights = np.sum(log_resp, axis=0) / np.sum(log_resp) denominator = np.sum(log_resp, axis=0, keepdims=True).T means_num = np.zeros_like(self.means) for k in range(self.n_components): means_num[k] = np.sum(np.multiply(x, np.expand_dims(log_resp[:, k], axis=1)), axis=0) self.means = np.divide(means_num, denominator) var_num = np.zeros_like(self.var) for k in range(self.n_components): var_num[k] = np.sum(np.multiply(np.square(np.subtract(x, self.means[k])), np.expand_dims(log_resp[:, k], axis=1)), axis=0) self.var = np.divide(var_num, denominator) def train(self, x): """ :param x: input array-like data """ log_resp = self.e_step(x) self.m_step(x, log_resp) def log_prob(self, x): """ :param x: input array-like data :return: calculated log gaussian probability of single modal Gaussian """ sum_prob = 0 for i in range(x.shape[0]): prob_i = np.array([np.log(self.weights[j]) + log_gaussian_prob(x[i], self.means[j], self.var[j]) for j in range(self.n_components)]) sum_prob += np.max(prob_i) return sum_prob 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 四、Isolated Speech Recognition - HMM 1. 隐马尔可夫模型 参考 hmmlearn 文档:https://hmmlearn.readthedocs.io/en/stable 隐马尔可夫模型(HMM, Hidden Markov Model) 是一种生成概率模型,其中可观测的 X XX 变量序列由内部隐状态序列 Z ZZ 生成。隐状态 (hidden states) 之间的转换假定为(一阶)马尔可夫链 (Markov chain) 的形式,可以由起始概率向量 π ππ 和转移概率矩阵 A AA 指定。可观测变量的发射概率 (emission probability) 可以是以当前隐藏状态为条件的任何分布,参数为 θ \thetaθ 。HMM 完全由 π ππ、A AA 和 θ \thetaθ 决定。 HMM 有三个基本问题: 给定模型参数和观测数据,估计最优隐状态序列 (estimate the optimal sequence of hidden states) 给定模型参数和观测数据,计算模型似然 (calculate the model likelihood) 仅给出观测数据,估计模型参数 (estimate the model parameters) 第一个和第二个问题可以通过动态规划中的维特比算法 (Viterbi algorithm) 和前向-后向算法 (Forward-Backward algorithm) 来解决,最后一个问题可以通过迭代期望最大化 (EM, Expectation-Maximization) 算法求解,也称为 Baum-Welch 算法。 如果想要直接调用封装好的库,只需在代码中加入 from hmmlearn import hmm,详情参见官方文档 和 源码。 2. 代码实现 对于本文的数字语音识别任务,HMM 模型的训练预测过程与 DTW 和 GMM 类似,不再重复说明。HMM 模型实现可以参考 hmmlearn 的源码,本文的实现关键在于 HMM 这个类中的函数。与 GMM 的 EM 算法不同的是,在 HMM 的实现中我们使用的是维特比算法 (Viterbi algorithm) 和前向-后向算法 (Forward-Backward algorithm)。 HMM 类包含两个参数 (parameter) 和四个属性 (attribute):n_components 表示模型中状态的数目;mfcc_data 为音频提取的 MFCC 数据;means 表示在每个状态中 mixture component 的平均值;var 为方差;trans_mat 是状态之间的转移矩阵。 class HMM(): """Hidden Markov Model. Parameters ---------- n_components : int Number of states in the model. mfcc_data : array, shape (, 39) Mfcc data of training wavs. Attributes ---------- init_prob : array, shape (n_components, ) Initial probability over states. means : array, shape (n_components, 1) Mean parameters for each mixture component in each state. var : array, shape (n_components, 1) Variance parameters for each mixture component in each state. trans_mat : array, shape (n_components, n_components) Matrix of transition probabilities between states. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 HMM 类中包含五个部分: __init__ 对参数进行初始化 (Initialization); viterbi Viterbi 算法用于解决 HMM 的解码问题,即找到观测序列中最可能的标记序列,本质上是一种动态规划算法 (dynamic programming); forward 计算所有时间步中所有状态的对数概率 (log probabilities); forward_backward 是参数估计的前向-后向算法 (Forward-Backward algorithm); train 用于调用 forward_backward 和 viterbi 进行参数训练; log_prob 计算每个模型的对数概率 (log likelihood)。 def viterbi(self, data): # Viterbi algorithm is used to solve decoding problem of HMM # That is to find the most possible labeled sequence of the observation sequence for index, single_wav in enumerate(data): n = single_wav.shape[0] labeled_seq = np.zeros(n, dtype=int) log_delta = np.zeros((n, self.n_components)) psi = np.zeros((n, self.n_components)) log_delta[0] = np.log(self.init_prob) for i in range(self.n_components): log_delta[0, i] += log_gaussian_prob(single_wav[0], self.means[i], self.var[i]) log_trans_mat = np.log(self.trans_mat) for t in range(1, n): for j in range(self.n_components): temp = np.zeros(self.n_components) for i in range(self.n_components): temp[i] = log_delta[t - 1, i] + log_trans_mat[i, j] + log_gaussian_prob(single_wav[t], self.means[j], self.var[j]) log_delta[t, j] = np.max(temp) psi[t, j] = np.argmax(log_delta[t - 1] + log_trans_mat[:, j]) labeled_seq[n - 1] = np.argmax(log_delta[n - 1]) for i in reversed(range(n - 1)): labeled_seq[i] = psi[i + 1, labeled_seq[i + 1]] self.states[index] = labeled_seq def forward(self, data): # Computes forward log-probabilities of all states at all time steps. n = data.shape[0] m = self.means.shape[0] alpha = np.zeros((n, m)) alpha[0] = np.log(self.init_prob) + np.array([log_gaussian_prob(data[0], self.means[j], self.var[j]) for j in range(m)]) for i in range(1, n): for j in range(m): alpha[i, j] = log_gaussian_prob(data[i], self.means[j], self.var[j]) + np.max( np.log(self.trans_mat[:, j].T) + alpha[i - 1]) return alpha def forward_backward(self, data): # forward backward algorithm to estimate parameters gamma_0 = np.zeros(self.n_components) gamma_1 = np.zeros((self.n_components, data[0].shape[1])) gamma_2 = np.zeros((self.n_components, data[0].shape[1])) for index, single_wav in enumerate(data): n = single_wav.shape[0] labeled_seq = self.states[index] gamma = np.zeros((n, self.n_components)) for t, j in enumerate(labeled_seq[:-1]): self.trans_mat[j, labeled_seq[t + 1]] += 1 gamma[t, j] = 1 gamma[n - 1, self.n_components - 1] = 1 gamma_0 += np.sum(gamma, axis=0) for t in range(n): gamma_1[labeled_seq[t]] += single_wav[t] gamma_2[labeled_seq[t]] += np.square(single_wav[t]) gamma_0 = np.expand_dims(gamma_0, axis=1) self.means = gamma_1 / gamma_0 self.var = (gamma_2 - np.multiply(gamma_0, self.means ** 2)) / gamma_0 for j in range(self.n_components): self.trans_mat[j] /= np.sum(self.trans_mat[j]) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 五、实验结果 Github 项目地址:https://github.com/Sherry-XLL/Digital-Recognition-DTW_HMM_GMM 1. 实验环境 macOS Catalina Version 10.15.6, Python 3.8, PyCharm 2020.2 (Professional Edition). 1 2. 文件简介 dtw.py: Implementation of Dynamic Time Warping (DTW) gmm.py: Implementation of Gaussian Mixture Model (GMM) hmm.py: Implementation of Hidden Markov Model (HMM) gmm_from_sklearn.py: Train gmm model with GaussianMixture from sklearn hmm_from_hmmlearn.py: Train hmm model with hmm from hmmlearn preprocess.py: preprocess audios and split data processed_test_records: records with test audios processed_train_records: records with train audios records: original audios utils.py: utils function 1 2 3 4 5 6 7 8 9 10 11 12 若想运行代码,只需在命令行输入如下指令,以 DTW 为例: eg: python preprocess.py (mkdir processed records) python dtw.py 1 2 3 3. 结果对比 各个方法的数据集和预处理部分完全相同,下面是运行不同文件的结果: python dtw.py ----------Dynamic Time Warping (DTW)---------- Train num: 160, Test num: 40, Predict true num: 31 Accuracy: 0.78 1 2 3 4 python gmm_from_sklearn.py: ---------- GMM (GaussianMixture) ---------- Train num: 160, Test num: 40, Predict true num: 34 Accuracy: 0.85 1 2 3 4 python gmm.py ---------- Gaussian Mixture Model (GMM) ---------- confusion_matrix: [[4 0 0 0 0 0 0 0 0 0] [0 4 0 0 0 0 0 0 0 0] [0 0 4 0 0 0 0 0 0 0] [0 0 0 4 0 0 0 0 0 0] [0 0 0 0 4 0 0 0 0 0] [0 0 0 0 0 4 0 0 0 0] [0 0 0 0 0 0 4 0 0 0] [0 0 0 0 0 0 0 4 0 0] [0 0 0 0 0 0 0 0 4 0] [0 0 0 0 0 0 0 0 0 4]] Train num: 160, Test num: 40, Predict true num: 40 Accuracy: 1.00 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 python hmm_from_hmmlearn.py ---------- HMM (GaussianHMM) ---------- Train num: 160, Test num: 40, Predict true num: 36 Accuracy: 0.90 1 2 3 4 python hmm.py ---------- HMM (Hidden Markov Model) ---------- confusion_matrix: [[4 0 0 0 0 0 0 0 0 0] [0 4 0 0 0 0 0 0 0 0] [0 0 3 0 1 0 0 0 0 0] [0 0 0 4 0 0 0 0 0 0] [0 0 0 0 4 0 0 0 0 0] [0 0 0 0 1 3 0 0 0 0] [0 0 0 0 0 0 3 0 1 0] [0 0 0 0 0 0 0 4 0 0] [0 0 0 1 0 0 1 0 2 0] [0 0 0 0 0 0 0 0 0 4]] Train num: 160, Test num: 40, Predict true num: 35 Accuracy: 0.875 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Method DTW GMM from sklearn Our GMM HMM from hmmlearn Our HMM Accuracy 0.78 0.85 1.00 0.90 0.875 值得注意的是,上面所得正确率仅供参考。我们阅读源码就会发现,不同文件中 n_components 的数目并不相同,最大迭代次数 max_iter 也会影响结果。设置不同的超参数 (hyper parameter) 可以得到不同的正确率,上表并不是各种方法的客观对比。事实上 scikit-learn 的实现更完整详细,效果也更好,文中三种方法的实现仅为基础版本。 完整代码详见笔者的 Github 项目,如有问题欢迎在评论区留言指出。 ———————————————— 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 原文链接:https://blog.csdn.net/Sherry_ling/article/details/118713802

CREATE TABLE IF NOT EXISTS sys_approval ( approval_id VARCHAR (64) NOT NULL COMMENT '审批单号(AP+年月日+6位序列)', process_type VARCHAR (50) NOT NULL COMMENT '流程类型', business_id VARCHAR (64) NOT NULL COMMENT '业务ID', applicant_id BIGINT (20) NOT NULL COMMENT '申请人ID', current_node VARCHAR (50) NOT NULL COMMENT '当前节点', status enum ( 'draft', 'pending', 'approved', 'rejected' ) DEFAULT 'draft' COMMENT '状态', create_time datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', update_time datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', PRIMARY KEY (approval_id), INDEX idx_business ( business_id, process_type ), FOREIGN KEY (applicant_id) REFERENCES sys_user (user_id) ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COMMENT = '审批流程主表'; [SQL]CREATE TABLE SMZQ_material_orders ( order_code VARCHAR (20) PRIMARY KEY COMMENT '单号(LY/DB+年月+4位序列)', order_type ENUM ('领用', '调拨', '报废') NOT NULL, apply_dept BIGINT (20) NOT NULL COMMENT '发起科室', applicant_id BIGINT (20) NOT NULL COMMENT '发起人', target_dept BIGINT COMMENT '目标科室(调拨专用)', approval_id VARCHAR (64) COMMENT '审批流程号', status ENUM ( '草稿', '审批中', '已通过', '已拒绝', '已完成' ) DEFAULT '草稿', complete_time DATETIME COMMENT '完成时间', create_time DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (apply_dept) REFERENCES sys_dept (dept_id), FOREIGN KEY (applicant_id) REFERENCES sys_user (user_id), FOREIGN KEY (approval_id) REFERENCES sys_approval (approval_id) ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '物资流转工单基表'; [Err] 3780 - Referencing column 'approval_id' and referenced column 'approval_id' in foreign key constraint 'smzq_material_orders_ibfk_3' are incompatible.

大家在看

recommend-type

高频双调谐谐振放大电路设计3MHz+电压200倍放大.zip

高频双调谐谐振放大电路设计3MHz+电压200倍放大.zip
recommend-type

只输入固定-vc实现windows多显示器编程的方法

P0.0 只输入固定 P0.1 P0CON.1 P0.2 P0CON.2 PORT_SET.PORT_REFEN P0.3 P0CON.3 自动“偷”从C2的交易应用程序在. PORT_SET.PORT_CLKEN PORT_SET.PORT_CLKOUT[0] P0.4 P0CON.4 C2调试的LED驱动器的时钟输入,如果作为 未启用. P0.5 PORT_CTRL.PORT_LED[1:0] 输出港口被迫为.阅读 实际LED驱动器的状态(开/关) 用户应阅读 RBIT_DATA.GPIO_LED_DRIVE 14只脚 不能用于在开发系统中,由于C2交易扰 乱输出. 参考区间的时钟频率 对抗 控制控制 评论评论 NVM的编程电压 VPP = 6.5 V 矩阵,和ROFF工业* PORT_CTRL 2 GPIO 1 矩阵,和ROFF工业* PORT_CTRL 3 参考 clk_ref GPIO 矩阵 4 C2DAT 产量 CLK_OUT GPIO 5 C2CLK LED驱动器 1 2 工业* PORT_CTRL 1 2 3 1 2 6 产量 CLK_OUT GPIO 1 2 1 1 1 PORT_SET.PORT_CLKEN PORT_SET.PORT_CLKOUT[1] P0.6 P0CON.6 P0.7 P0CON.7 P1.0 P1CON.0 P1.1 P1CON.1 7 8 9 GPIO GPIO GPIO 14只脚 14只脚 14只脚 *注:工业注:工业 代表“独立报”设置. “ 矩阵矩阵 and Roff 模式控制模拟垫电路. 116 修订版修订版1.0
recommend-type

半导体Semi ALD Tungsten W and TiN for Advanced Contact Application

ALD Tungsten, W and TiN for Advanced Contact Application
recommend-type

声纹识别数据集 IDMT-ISA-ELECTRIC-ENGINE

包含发动机正常、高负荷、损坏三种状态.wav声音片段,每种状态包含几百个片段,每个片段时长3S,可用于声纹类型识别,包含数据集介绍文档。
recommend-type

StepInt3-Plugin-x64:StepInt3插件(x64)-x64dbg的插件

StepInt3插件(x64)-x64dbg的插件 有关此插件的x86版本,请访问 概述 一个插件来解决int3断点异常 特征 自动跳过int3断点异常 从插件菜单启用/禁用的选项 如何安装 如果当前正在运行x64dbg(x64dbg 64位),请停止并退出。 将StepInt3.dp64复制到x64dbg\x64\plugins文件夹中。 启动x64dbg 信息 由撰写 使用 RadASM项目(.rap)用于管理和编译插件。 RadASM IDE可以在下载 该插件的x64版本使用 要构建此x64版本,还需要。 x64dbg x64dbg github x64dbg开关

最新推荐

recommend-type

kernel-4.19.90-52.29.v2207.ky10.x86-64.rpm

kernel-4.19.90-52.29.v2207.ky10.x86-64.rpm
recommend-type

2025年检验检测机构评审准则宣贯试题(附答案).pdf

2025年检验检测机构评审准则宣贯试题(附答案).pdf
recommend-type

STM32F4 SDIO应用示例代码

STM32F4 SDIO应用示例代码
recommend-type

多数据源管理与分表实践:MybatisPlus与ShardingJdbc整合

根据给定的文件信息,我们可以详细地解读其中涉及到的关键知识点,这些知识点包括Mybatis Plus的使用、ShardingJdbc的数据分片策略、Swagger的API文档生成能力,以及如何通过注解方式切换数据源。以下是详细的知识点分析: ### Mybatis Plus Mybatis Plus是一个Mybatis的增强工具,在Mybatis的基础上只做增强不做改变,为简化开发、提高效率而生。Mybatis Plus提供了如CRUD、分页、多数据源等一些列增强功能,并且可以与Spring、Spring Boot无缝集成。 #### 使用Mybatis Plus的优势: 1. **简化CRUD操作**:Mybatis Plus自带通用的Mapper和Service,减少代码量,提高开发效率。 2. **支持多种数据库**:支持主流的数据库如MySQL、Oracle、SQL Server等。 3. **逻辑删除**:可以在数据库层面实现记录的软删除功能,无需手动在业务中进行判断。 4. **分页插件**:提供默认的分页功能,支持自定义SQL、Lambda表达式等。 5. **性能分析插件**:方便分析SQL性能问题。 6. **代码生成器**:可以一键生成实体类、Mapper、Service和Controller代码,进一步提高开发效率。 #### 关键点: - **代码生成器**:位于`com.example.demo.common.codegenerator`包下的`GeneratorConfig`类中,用户需要根据实际的数据库配置更改数据库账号密码。 ### ShardingJdbc ShardingJDBC是当当网开源的轻量级Java框架,它在JDBC的层次提供了数据分片的能力。通过ShardingJDBC,可以在应用层面进行分库分表、读写分离、分布式主键等操作。 #### 分库分表: - 通过ShardingJDBC可以配置分库分表的策略,例如按照某个字段的值来决定记录应该保存在哪个分库或分表中。 - **Sharding策略**:可以定义多种分片策略,如模运算、查找表、时间范围等。 #### 关键点: - **注解切换数据源**:文件中提到通过注解的方式切换数据源,这允许开发者在编写代码时通过简单注解即可控制数据访问的路由规则。 ### Swagger Swagger是一个规范且完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务。总体目标是使客户端和文件系统作为服务器以同样的速度来更新。Swagger文件可让机器读取以了解远程服务的功能,并且可以作为浏览器插件,以便用户与远程服务互动。 #### 使用Swagger的优势: 1. **API文档自动生成**:Swagger可以根据代码中的注释直接生成文档。 2. **动态接口测试**:可以动态地对API接口进行测试。 3. **交互式文档**:提供交互式的API文档,可以实时地在线测试API。 #### 关键点: - **动态文档**:项目中集成Swagger后,可以在开发过程中动态更新API文档,便于团队协作和文档维护。 ### 如何使用 1. **准备工作**:在解压之前,需要更改数据源的IP、账号和密码,并执行resources下的SQL脚本。 2. **数据源配置**:在实际使用中,需要根据实际情况更改GeneratorConfig类中的dataSourceConfig()的数据库账号密码。 3. **代码生成**:启动代码生成器,根据设定的模板和策略生成相应的代码,包含实体类、Mapper、Service和Controller等。 4. **分库分表配置**:配置ShardingJDBC的分库分表策略,包括分片键和分片算法等。 5. **API文档**:集成Swagger,自动生成API文档并提供动态测试功能。 ### 结语 通过本文件所描述的内容,我们可以了解到如何利用Mybatis Plus、ShardingJdbc、Swagger这三大工具配合实现复杂的数据库操作和维护,以及如何通过注解在不同数据源之间灵活切换。用户在使用时应严格按照文件中的指示进行操作,确保数据库连接信息的正确配置,并结合代码生成器快速搭建项目基础结构。同时,应充分理解ShardingJdbc的分库分表策略,以及Swagger的API文档管理功能,以优化开发流程和提高工作效率。如果以上内容使用得当,这将是一个能够有效提升项目开发和维护质量的强大工具集。
recommend-type

BLE广播机制深度解析:XN297_TO_BLE.zip中的创新实践与应用指南

# 摘要 本文全面分析了蓝牙低功耗(BLE)广播机制的理论与实践应用,特别关注了XN297_TO_BLE.zip的开发与优化。通过详细探讨BLE广播的工作原理、数据包结构、以及XN297_TO_BLE.zip的设计理念与架构,本文为开发者提供了深入了解和实践BLE技术的框架。文中不仅介绍了如何搭建开发环境和编程实践,还深入讨论了
recommend-type

我用的就是idea的内置maven呀

<think>好的,用户现在提到他们使用的是IDEA的内置Maven,但之前遇到了“mvn不是内部或外部命令”的问题。我需要仔细分析可能的场景和用户的需求。 首先,用户可能是在IDEA内部使用Maven时没有问题,但在外部命令行中使用mvn命令时遇到了问题。这说明用户可能混淆了IDEA内置Maven和系统环境变量配置的关系。内置的Maven只在IDEA内部有效,并不会自动配置系统的环境变量,因此当用户在命令行中直接运行mvn时,系统找不到该命令,导致报错。 接下来,我需要确定用户的具体使用场景。用户可能是在尝试通过命令行执行Maven命令,或者是在其他需要系统环境变量支持的地方使用mvn。
recommend-type

环保主题植树节PPT模板设计赏析

标题“清新淡雅绿色环保植树节ppt模板”和描述“茂密的一棵卡通树,散落的绿叶,藤蔓线条,清新淡雅,绿色环保,312植树节ppt模板”共同体现了该PPT模板的设计风格和主题。该模板旨在宣传和庆祝植树节,同时强调了环保的理念。以下是对标题和描述中所蕴含知识点的详细说明: 1. 植树节的概念 植树节,是为了提高人们对森林资源的认识、倡导植树造林而设定的节日。不同国家的植树节日期可能不同,而在中国,“312”植树节(每年的3月12日)被广泛认知和庆祝。这个节日起源于20世纪初,是纪念孙中山先生的逝世纪念日,并逐渐演变为全民植树造林的活动日。 2. 绿色环保理念 绿色环保是指在人类活动中,采取相应的措施减少对环境的破坏,保护地球的自然资源和生态系统。这包括节能减排、资源循环利用、减少废弃物产生、提高能源效率等方面。该PPT模板采用“清新淡雅”的视觉元素,通过卡通形象和自然元素来传递环保的理念,使人们对环保有更深的认同感。 3. 卡通风格设计 模板使用了卡通风格来呈现内容,卡通风格设计通常更加生动、活泼,易于吸引观众的注意力,尤其适合儿童及青少年教育和宣传场合。卡通化的树木和藤蔓线条,可以更好地将植树节这一主题与观众尤其是年轻一代进行连接。 4. 清新淡雅的设计风格 “清新淡雅”是一种设计理念,强调色彩的温和、简洁的布局和舒适的视觉体验。在设计中,它通常表现为使用柔和的色调、简单的图形和没有过多装饰的版面,以创造出一种宁静、舒适的感觉。这种风格的模板适合用于教育、公益宣传等场合,易于传达温暖、积极的信息。 5. PPT模板的应用 PPT(PowerPoint演示文稿)是微软公司开发的一款演示软件,广泛用于商业汇报、教育授课、会议演讲和各类展示活动。一个精心设计的PPT模板可以提高演示的专业性和观赏性,同时通过统一的风格和格式,帮助使用者节省准备演示的时间和精力。模板中预设的版式、字体和配色可以被用户根据自己的需求进行调整和补充内容。 结合以上知识点,可以得出这个植树节PPT模板的设计意图和使用价值。它不仅具有美化演示文稿的作用,而且通过其环保主题和设计风格,传达了植树造林、保护环境的重要性。模板的视觉元素如卡通树木和藤蔓线条等,使得环保理念的表达更为直观和亲民,适合在植树节等环保主题活动上使用。
recommend-type

BLE调试必备:XN297_TO_BLE.zip故障排除与性能监控手册

# 摘要 本文详细介绍了BLE技术的基础知识,并针对XN297_TO_BLE.zip这一软件包进行了深入分析。通过对安装、配置、故障排查、性能优化、高级功能实现及案例研究等方面的探讨,提供了全面的实施指导和最佳实践。文章首先概括了BLE技术的核心要点,随后重点阐述了XN297_TO_BLE.zip的安装、初始配置以及功能验证,特别是在连接故障诊断、数据同步问题解决、性能
recommend-type

开源 文件管理

<think>好的,用户想找关于开源文件管理系统的信息,包括工具、项目或解决方案。首先,我需要回忆一下相关的开源项目。根据之前的引用,用户提到过Redmine、Taiga、ProjectLibre等开源项目管理软件,但可能这些更多是项目管理而非专门的文件管理。不过,用户还提到了Gollum,这是一个基于Git的文档管理系统,可能更贴近文件管理。 接下来,我需要区分文件管理系统和项目管理系统的不同。文件管理更侧重于文档的存储、版本控制、权限管理等,而项目管理则涉及任务跟踪、协作等。因此,可能需要专门针对文件管理的工具。比如,Nextcloud和OwnCloud都是开源的云存储解决方案,适合文件
recommend-type

CISP标准课件V4.2:信息安全与系统保障全面指南

在详细阐述CISP课件V4.2标准版的知识点之前,我们首先需要明确几个概念。首先,“CISP”指的是“Certified Information Security Professional”(注册信息安全专业人员),这是一个在信息安全领域内认可的专业认证资格。而“CISE”和“CISO”则是指信息安全工程师(Certified Information Security Engineer)和信息安全官(Certified Information Security Officer)的认证,它们都属于CISP的范畴。此外,“CISM”指的是“Certified Information Security Manager”(注册信息安全经理),这是另一个与CISP相关的信息安全专业认证。 根据给出的标题和描述,这份CISP课件V4.2标准版是针对上述信息安全相关认证的教材和学习资源,涵盖了信息安全领域中各类专业人士需要掌握的核心知识。课件的内容体系是以模块化的方式组织的,包括知识域、知识子域和知识点三个层次。具体地,以下是对这份课件中提及的知识点的详细解释: 1. 知识体系模块化结构 - 知识体系:指的是课件内容的整体框架,它将复杂的信息安全知识划分成不同的模块,便于学习者理解和记忆。 - 知识域:指的是整个信息安全领域内的一大类知识主题,例如“信息安全保障”、“网络安全监管”等。 - 知识子域:是在知识域基础上细分出来的子主题,它们构成了实现知识域目标的具体内容。 - 知识点:是在知识子域中进一步细分的小知识点,是学习者需要掌握的基础内容。 2. 知识点掌握程度分类 - 了解:这是基础层级,学习者需要对知识点的基本概念和原理有所认识,但不涉及深层次的应用和分析。 - 理解:这个层次要求学习者不仅了解知识点的基础概念和原理,还能够深入理解其内容,并在此基础上进行判断和推理。 - 掌握:这是最高层级,学习者不仅要了解和理解知识点,还必须能够在实践中灵活运用所学知识,解决实际问题。 3. 知识体系结构涵盖的知识域 - 信息安全保障:涉及组织和机构在信息安全方面的整体策略和措施。 - 网络安全监管:关注如何监管和管理网络安全,以保障网络空间的安全性。 - 信息安全管理:包括信息资产保护、安全政策和程序的制定与实施等内容。 - 业务连续性:讨论如何确保组织在发生信息安全事件后的业务连续性和恢复。 - 安全工程与运营:涉及安全系统的设计、实施和运维管理。 - 安全评估:包括信息安全风险评估和审计等评估活动。 - 信息安全支撑技术:介绍支持信息安全的关键技术和工具。 - 物理与网络通信安全:讲述如何保护物理资产和网络通信不受威胁。 - 计算环境安全:涉及服务器、工作站和其他计算环境的安全保护。 - 软件安全开发:着重于在软件开发过程中如何实现安全性。 综上所述,CISP课件V4.2标准版是一份综合性的学习资源,旨在通过模块化和层次化的方式,帮助信息安全相关专业人士深入掌握信息安全领域的专业知识和技能。这份课件不仅适合作为教材和教学资源,还能够作为学习者自我提升和考核的知识依据。此外,这份课件的文件名称列表中只列出了一个文件名称“CISP课件V4.2标准版 20190214”,表明当前获取的资源是一个特定版本的压缩包文件。在实际使用中,需要解压这个文件以获取其中的教学内容和材料。