- 2024-11-01
-
回复了主题帖:
《人工智能实践教程》--卷积神经网络CNN
freebsder 发表于 2024-10-28 15:09
AlexNet 一炮而火,确实经典。
是的。学习AI,要善于借助资源工具平台
- 2024-10-21
-
回复了主题帖:
《人工智能实践教程》--卷积神经网络CNN
Jacktang 发表于 2024-10-21 07:49
卷积神经网络CNN确实听所过,看来想弄懂还得像楼主这样,好好读书
哈,多学习总是好的
- 2024-10-20
-
发表了主题帖:
《人工智能实践教程》--卷积神经网络CNN
卷积神经网络(ConvolutionalNeura! Network,CNN)。CNN 可用于图像识别语音识别等场合。
1.整体结构
CNN可以通过组装层进行构建,CNN中有卷积层(Convolution层)和池化层(Pooling层)。 CNN常见网络结构
2.卷积层
在CNN中会出现了一些特有的术语,如填充、步幅等。此外,各层中传逸的据是有形状的数据。
卷积层可以保持形状不变。当输入数据为图像时,卷积层会以3维数据的形式接收输入数据,并以3维数据的形式输出至下一层。因此,在CNN中,卷积层可以正确“理解图像等具有形状的数据。有时将卷积层的输入/输出数据称为特征图(Feature Map),其中,卷积层的输入数据称为输入特征图(InputFeature Map),输出数据称为输出特征图(OutpuFeature Map).
卷积层进行卷积运算,卷积运算相当于图像处理中的“滤波器运算”。
在进行卷积层的处理前,有时要向输入数据的四周填入固定的数据(比如0等),这称为填充(padding),填充在卷积运算中经常会用到。
应用滤波器的位置间隔称为步幅(side)。如果增大步幅,那么输出数据的大小会变小;如果增大填充,那么输出数据的大小会变大。
三维数据的卷积运算--三维数据进行卷积运算,除高、宽方向外,还包括通道方向。
在神经网络的实现中,进行了将输入数据打包的批处理。
3.池化层
池化是一种缩小高、宽方向上的空间的运算。池化层的特征:没有要学习的参数;通道数不发生变化;对微小的变化具有鲁棒性。
通过使用一些技巧,可以轻松地实现卷积层和池化层。本节将介绍这些技巧,首先将问题简化,然后再进行实现。
池化层的实现与卷积层的实现相同,也使用im2col函数展开输入数据。不同的是在池化时,通道方向上是独立的。池化的应用区域按通道单独展开的。
4.卷积神经网络可视化
卷积层权重的可视化--卷积层的滤波器能提取边缘或斑块等原始信息,并且CNN会将这些原始信息传递给后面的层。
基于分层结构的信息提取--在堆叠多层的 CNN中,从各层分别能提取,会发现从越靠后的层中提取的信息越抽象(神经元反应更强烈)。
5.具有代表性的卷积神经网络。
LeNet 是进行手写数字识别的网络。,LeNet 有如下几个特点:
一是激活函数。LeNet 使用 Sigmoid 函数作为激活函数,而现在的 CNN 主要使用 ReLU函数作为激活函数。
二是原始的 LeNet 使用子采样(Subsampling)缩小中间数据的大小,而在现在的CNN使用 Max 池化缩小中间数据的大小。
AlexNet 是引发深度学习热潮的导火线,它的网络结构与LeNet基本相同,但有如下几个不同点。
激活函数使用 ReLU。
使用进行局部正规化的LRN(LocalResponse Normalization)层。
使用 Dropout 方法,Dropout方法是指在深度学习网络的训练过程中,对于神经网络单元,按照一定的概率将其暂时从网络中丢弃。
卷积神经网络CNN是大家比较耳熟能详的,通过阅读学习,对卷积神经网络有了进一步认识与理解掌握,常学常新。
- 2024-10-15
-
回复了主题帖:
【匠芯创D133CBS】--6.LVGL界面移植
yangjiaxu 发表于 2024-10-15 09:00
你好,大佬,我昨晚试了一下在meconfig中没找到,能大致说说me配置,关于PSRAM路径吗?还是因为工程的不 ...
- 2024-10-14
-
回复了主题帖:
【匠芯创D133CBS】--6.LVGL界面移植
yangjiaxu 发表于 2024-10-13 20:41
大佬您好,这个SRAM_S0溢出报错,这时配置到PSRAM即可,这里一般怎么配置呀?
都选psram,配置命令里可以找到
- 2024-09-28
-
发表了主题帖:
【匠芯创D133CBS】--10.LVGL界面设计
本篇讲述使用GUI-Guider工具设计LVGL界面。
一.GUI-Guider工具使用
1.创建工程
图1:工具创建界面工程
2.设计界面
这里使用工具自带的插件。首先加上文本标题,设置字体及大小。下面添加了六个组件,有按键、选择开关、下拉框,滑动选择条,滚动条等。这里可以配色及形状等选择,设计好后界面如下。
图2:界面设计与模拟仿真
3.模拟仿真。点击上图红框所示,软件会运行弹出界面,可以模拟操作看效果这些,根据需要可以调整。运行后会生成界面代码。
二.代码准备
1.选取生成代码取如下红框内如下图,
图3:选取代码移植
2.迁移到工程目录下如图
图4:工程添加
三.测试
编译烧录后,界面如下,触摸组件有相应效果,LVGL 界面设计达到预期。
图5:界面实际效果
[localvideo]8e3e0b4dc0b69a4e3c40936c1f3c0d67[/localvideo]
- 2024-09-25
-
回复了主题帖:
《拥抱AIGC》--总结与读后感
chejm 发表于 2024-9-25 13:14
感谢楼主分享的AIGC的相关内容,希望后续能看到一些AIGC有关的应用案例
可以有,技术发展挺快的,最近听说有生成视频这些的了。根据需要,侧重选择。
- 2024-09-24
-
回复了主题帖:
《拥抱AIGC》--总结与读后感
Jacktang 发表于 2024-9-23 07:24
说的不错,对于终端用户来说,AIGC是一个很好的工具。
是的,有需要可以多多尝试与使用
- 2024-09-21
-
回复了主题帖:
《拥抱AIGC》--全书概览及生成式人工智能OpenAI和ChatGPT基础
freebsder 发表于 2024-8-16 16:07
很有意思,我们目前都在尝试用大语言模型做一些事情。
是人工智能发展潮流了,身边也有挺多人在用这方面的
-
发表了主题帖:
《拥抱AIGC》--总结与读后感
本书主讲生成式人工智能(AIGC),以ChatGPT与OpenAI为主轴线进行讲解。全书分三大部分:第一部分介绍生成式人工智能概念--生成式人工智能与GPT模型基础;第二部分介绍使用ChatGPT,包括了ChatGPT助力生产力提升、助力软件开发、助力营销、助力科学研究等。这部分是全书的精华与重点,各行各业可以从中选择性学习与使用。第三部分介绍OpenAI模型在企业级场景中的应用。通览全书,这本书对AIGC入门还是很有帮助的。
虽然在国内目前属于不支持服务状态,书中内容也不太好原样演练修习,但有一个模板在,也可以带领我们去了解AIGC、获得启迪。这也给国产AI的崛起与应用提供了挑战与机遇。实际上,一些国内大厂如阿里、百度、腾讯、科大讯飞等都有大模型训练等这方面的投入发展与应用,有浏览到资讯与国外并不落后多少,并且资费上相对便宜。别人好的地方我们多学习,并进行本土化与市场开拓发展,潜力还是很巨大的。对于终端用户来说,AIGC是一个很好的工具,可以帮助我们既快又好的完成一些事情。AI的发展是技术潮流趋势,同时也存在道德等方面挑战。AI对人工的替代也是一个广泛讨论的话题。我们既要拥抱AIGC,因为这是一个科技日新月异的时代,同时要掌握好AIGC,用好AIGC,为个人与社会服务,需要我们辩证去看待,积极学习与应对。
“君子性非异也,善假于物也”,引用一段古语,为这本书做注解,也是心得体会。
- 2024-09-15
-
发表了主题帖:
【匠芯创D133CBS】--9.以太网测试
本帖最后由 dirty 于 2024-9-15 23:57 编辑
开发板板载RMII接口百兆以太网,可以支持有线网络通讯。同时裕留有SDIO接口(RTL8723DS),支持无线WIFI。本篇讲述以太网功能及测试。
一.硬件原理
以太网(Ethernet)是一种计算机局域网组网技术,基于 IEEE802.3 标准,它规定了包括物理层的连线(RJ45),电气信号(PHY)和媒体访问层(MAC)协议等, 以太网的特征是有线网络,网络中的各终端必须通过网线进行连接,以太网模块可以简单的理解为 MAC 通过 MII 总线控制 PHY 共同完成终端之间数据交换的一种设备。
以太网电路包括:RJ45 连接器、网络变压器、晶振、PHY 收发器、MAC 控制器、AP 处理器等,下面是电路原理图,插好网线。
图1:以太网电路
图2:开发板插上网线
二.软件配置准备
1.根据硬件电路图,对PHY端口信号对应引脚进行定义,在target/d13x/demo88-nor/pinmux.c如下
图3:以太网引脚定义
2.MAC参数配置.这里PHY复位引脚根据电路填上,选择RMII,关于IP地址,静态的选择和电脑一个段内的。
图4:MAC配置
3.LwIP协议配置.这里选择使用DHCP 动态IP分配。
图5:LwIP协议配置使用动态IP
4.打开LwIP调试信息选项,一共后面测试使用。这里也可根据需要使用支持MQTT协议.
图6:使能LwIP调试信息
至此,配置完毕。
三.测试
编译烧录后,可以查看到LwIP启动,获取到IP,日志如下
图7:获取网络IP
在PC端ping开发板IP,可以看到PC端收到回包,设备端也有响应
图8:Ping包
至此,对开发板以太网功能进行了评估测试,开发板具备以太网功能。
- 2024-09-02
-
发表了主题帖:
【匠芯创D133CBS】--8.音频录放测试
本帖最后由 dirty 于 2024-9-3 09:48 编辑
本篇讲述测试开发板音频录放功能。
一.硬件原理与准备
开发板板载两颗数字麦克风,左右声道,用于录音,硬件原理如下图。DMIC_CKL 数字麦克风时钟,DMIC_DATA 数字麦克风数据。
图1:数字麦克风原理
开发板留有喇叭接口,功放电路由功放开关PD10引脚和数字PWM输出PE12引脚控制,原理如下图。这里准备了4Ω 3W喇叭接在开发板端子上,插上SD卡。
图2:喇叭功放电路原理
图3:音频录放硬件准备
二.音频配置
这里使用Audio Codec 模块,其内置 Sigma-Delta ADC、 DMIC 接口和 PWM 音频输出,经过数字信号的处理,实现音频信号的录入以及播放等功能。
1.驱动配置使能及Audio参数配置。这里使用了播放功能,需要选择Usingplayback;这里配置了喇叭功放开关引脚、其触发电平及喇叭通道选择。使用 DMIC 录音,则需要选择Using DMIC。
图4:Audio驱动使能与参数配置
2.系统驱动框架配置
这里使用了RT-Thread系统的audio驱动框架实现Audio模块的driver层驱动,其配置如下
图5:系统音频驱动框架配置
3.音频录放测试代码实现,sound_arecord实现录一段音频,sound_aplay实现播放该音频。这里在SD卡里预先放一个wav音频文件,录音会查找打开并记录进文件。
图6:音频路放测试代码实现
至此,音频录放配置准备与相关代码就绪。
三.测试
编译烧录后,开发板系统启动,输入命令:arecord /sdcard/test.wav 开始一段录音,aplay /sdcard/test.wav播放该音频。日志如下
图7:音频录放测试日志
下面是音频录放实际效果视频,主要听声音。正对MIC方位声音会较响亮些,同时这音频也比较原生,这里只作功能性验证了,跟软硬件方面都会有些关系,后面可以视情况更深入研究。
[localvideo]edb6bf94468577fafd52dee3e383b790[/localvideo]
至此,实现开发板音频录放功能性验证。
- 2024-09-01
-
发表了主题帖:
《拥抱AIGC》--ChatGPT应用
本篇内容主要讲解ChatGPT应用之熟悉ChatGPT、提示设计及助力软件开发。由于前阵子OpenAI对国内停服,很多书上实验也做不了,目前只能是对生成式AI做一些熟悉了解,转移到国内AI大模型,如讯飞星火,文心一言等使用与尝试。
●熟悉ChatGPT
熟悉ChatGPT主要包括设置 ChatGPT账户,熟悉界面,组织聊天以及构建对话。这一块主要是注册熟悉与使用。
●了解提示设计
在生成式人工智能的上下文中,提示是指用户提供给生成模型的输入。提示是用户控制模型生成输出的唯一方式。定义明确的提示是成功对话的秘诀,足以涵盖感兴趣的主题。
OpenAI模型(包括ChatGPT)以预训练的形式提供服务这些模型已经基于大量数据训练过,并且根据其(数十亿计的)参数进行了配置,这些模型可以再学习。自定义OpenAI模型并使其能处理特定任务的一种方法是微调。书中讲到样本学习,零样本学习,一次样本学习,小样本学习的概念与解说,可以从另一角度了解模型功能。
提示最佳实践做法:清晰、简洁、聚焦、一致、扮演角色。应避免:信息过载、开放式问题、缺乏约束。
ChatGPT纳入道德伦理考量,像前几天360儿童手表社会问题,所以生成式AI也需要一定的法律道德约束和技术上的完善管理。
●ChatGPT助力软件开发
相信这个对软件工程人员来说很吃香,同时也会引起人工智能替代人工的广泛讨论。
ChatGPT最令人惊叹的功能之一是其处理代码的能力--它可以处理任何类型的代码。Python、JavaScript、SQL和C#是目前人们经常使用的编程语言,而 ChatGPT所能理解和生成的编程语言如下图所示。
图1:ChatGPT支持的编程语言
ChatGPT的主要功能之一就是代码生成,其还能解释函数的功能、用法、优化、错误地方等。ChatGPT还可以使用自然语言来解释脚本、函数、类或其他类似事物的作用。
ChatGPT在不同语言间有极强的转换能力。ChatGPT能够在不同的编程语言之间进行转换,同时保持相同的输出和相同的风格。
ChatGPT可以成为应用程序现代化的有效工具,可提供代码升级并为增强遗留系统提供有价值的见解和建议。凭借其先进的语言处理能力和广泛的知识库ChatGPT 可以帮助组织简化其现代化工作,使整个过程更快、更高效。
下面用文心一言做下相关试验,分别询问天气和创建求两数最大数函数,结果还不错。
图2:询问天气
图3:生成代码
总的来说,学习掌握AIGC工具的使用,对各行各业来说确实可以带来很多便利、高效。AI是当前热门发展潮流,学会使用对我们来说也会很有助益。
-
发表了主题帖:
【匠芯创D133CBS】--7.SD卡挂载与文件读写
本篇讲述SD卡挂载与文件读写。通过按键触发读SD卡文件,初次没有则创建,读到文件后打印出来。
一.硬件原理
开发板主控SOC有SD/MMC控制器(简称SDMC),支持访问 SD 卡/ eMMC/ SDIO 设备,有硬件原理如下可知使用到SDMC1,开发板上有SD卡座,插上SD卡。
图1:SD卡接口原理
二.代码准备
本部分分为SD卡挂载 和 SD卡文件读写,下面分别展开讲述。
●.SD卡挂载
1.配置SDMC接口,这里根据硬件原理使用SDMC1
图2:SD接口配置
2.设置自动挂载,这里稍微改写board.c里挂载表mount_table,如下
图3:设置自动挂载
3.热拔插配置。目前Lite 下只实现了 SDMC1 热插拔,刚好可以支持到。
图4:SD卡热拔插配置
至此,SD卡挂载配置与准备完成。
●.SD卡文件读写
此部分实现的功能是:使用按键触发文件读写,初次SD卡没有打开读的文件则创建,读到文件则直接打印出来。
1.SD卡读写使用到文件系统,下面配置文件系统。此处需要打开 RT-Thread 中的 elm(即 FatFS 文件系统)
图5:文件系统配置
2.定义SD卡根路径,申请文件读写内存大小FILE_DATA_LEN ,以及消息发送数据结构体及消息分类。
#define SD_PATH "sdcard/"
#define FILE_DATA_LEN_64K 64*1024
#define FILE_DATA_LEN_16K 16*1024
#define FILE_DATA_LEN 5*1024
typedef enum
{
MSG_LED_BUZZER,
MSG_SD,
}MSG_EVT_TYPE;
typedef struct
{
uint8_t msg_type;
uint16_t msg_len;
uint8_t led_value;
uint8_t buzzer_pwm_percent;
}msg_control;
3.在按键中断发送SD卡操作消息队列
static void key_irq_handler(void *args)
{
unsigned int ret;
u32 pin = *((u32 *)(args));
printf("Key INT \r\n");
memset(&msg_control_t,0,sizeof(msg_control));
msg_control_t.msg_type=MSG_SD;
msg_control_t.msg_len=sizeof(msg_control_t);
app_msg_send(&msg_control_t,sizeof(msg_control_t));
}
4.在消息队列接收任务里实现SD卡文件的读写。里面添加的日志可以便于后面测验。
void app_thread_entry(void *parameter)
{
FILE *fp;
char file_path[128] = { 0 };
char *data;
int ret;
int pin;
msg_control msg_control_p;
while(1)
{
if(rt_mq_recv(&user_mq, &msg_control_p, sizeof(msg_control_p), RT_WAITING_FOREVER)==RT_EOK)
{
rt_kprintf("Receive msg quene.msg_type:%d,msg_len:%d\r\n",msg_control_p.msg_type,msg_control_p.msg_len);
switch(msg_control_p.msg_type)
{
case MSG_LED_BUZZER:
rt_kprintf("led_value:%d,buzzer_pwm_percent:%d%%\r\n",\
msg_control_p.led_value,msg_control_p.buzzer_pwm_percent);
pin = rt_pin_get(LED_PIN);
rt_pin_write(pin, msg_control_p.led_value);
hal_pwm_set(BUZZER_PWM_CH, msg_control_p.buzzer_pwm_percent*BUZZER_FREQ_PARAM/100, BUZZER_FREQ_PARAM,PWM_SET_CMPA_CMPB);
break;
case MSG_SD:
data = aicos_malloc_align(0, FILE_DATA_LEN, CACHE_LINE_SIZE);
if (data == NULL)
{
rt_kprintf("Low memory\r\n");
return;
}
rt_kprintf("To Read File...\r\n");
rt_sprintf(file_path, "%s%s", SD_PATH,"test.txt");
fp=fopen(file_path,"rb");
if(fp==NULL)
{
rt_kprintf("Open read file %s failed!\n", file_path);
fclose(fp);
fp=fopen(file_path,"wb");
if (fp == NULL)
{
printf("create file %s failed!\n", file_path);
}
else
{
rt_kprintf("Open write file %s OK!\n", file_path);
rt_sprintf(data, "%s","你好,欢迎使用匠芯创开发板");
ret=fwrite(data, sizeof(char), FILE_DATA_LEN, fp);
{
rt_kprintf("Write file Success! size:%d\n", ret);
rt_kprintf("Write file Content:\r\n%s\r\n", data);
}
}
fclose(fp);
aicos_free_align(0, data);
}
else
{
rt_kprintf("Open read file %s OK!\n", file_path);
ret=fread(data, sizeof(char), FILE_DATA_LEN, fp);
if(ret)
{
rt_kprintf("Read file Success! size:%d\n", ret);
rt_kprintf("Read file Content:\r\n%s\r\n", data);
}
fclose(fp);
aicos_free_align(0, data);
}
break;
default :
break;
}
}
}
}
下面是工程关于SD卡读写的逻辑功能代码结构。至此代码准备完毕。
图6:SD卡读写工程
三.测试
编译烧录后,下面开始测验,同样分两部分进行:SD卡挂载,SD卡文件读写。
1.查询SD卡设备,使用命令list_device,如下
图7:SD卡识别
2.按一下WEAKUP按键,可以看到没有文件则创建文件并写入数据。再按之后,可以读出文件。命令切入到SD卡下,可以查询到创建了test.txt文件。
图8:SD卡读写日志
至此,成功挂载SD卡,并实现了文件的读写。
- 2024-08-31
-
发表了主题帖:
【匠芯创D133CBS】--6.LVGL界面移植
本帖最后由 dirty 于 2024-8-31 23:30 编辑
本篇梳理讲述SDK LVGL框架功能,并移植自定义LVGL demo界面功能。
一.系统框架LVGL
RTOS SDK已经移植了LVGL,其库如下图所示框架部分。
图1:LVGL库框架
LVGL的入口为lvgl_thread_init,其被RT-Thread系统初始化导入。在任务lvgl_thread_entry里实现了LVGL显示触摸初始化:函数 lv_port_disp_init()中实现显示接口的对接以及硬件 2D 加速的对接;函数 lv_port_indev_init()中实现触摸屏的对接;函数 aic_dec_create()注册硬件解码器。lv_timer_handler(),lv_tick_get()给了LVGL一个心跳。lv_task_handler()处理LVGL任务。关于LVGL库,SDK是移植配套好了。用户LVGL应用在aic_ui_init里实现。
二.移植自定义LVGL
1.GUI-Guider工具界面配置如下,注意适配屏幕分辨率1024*600,色深16bit。这里用现成的模板稍作修改,使用Simulator仿真模式。
图2:GUI-Guider配置
2.稍作修改,生成C界面源码,操作如下
图3:生成界面源码
3.取需要使用源码如下,移入到SDK aci_demo路径下,这里放在自建app_user_ui下,如下图所示。 后面以模板化编写,后面界面更改变动基本只需将如下图所示部分替换即可。
图4:界面C源代码部分植入工程
4.创建app_user_ui.c/.h文件,编写用户统一界面代码接口函数如下
/*
packages/artinchip/lvgl-ui/aic_demo/app_user_ui/app_user_ui.c
*/
#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include "lvgl.h"
#include "aic_ui.h"
#include "lv_port_disp.h"
#include "mpp_fb.h"
#include "app_user_ui.h"
#include "gui_guider.h"
lv_ui guider_ui;
void app_user_ui_init()
{
/* 用户APP 入口 */
setup_ui(&guider_ui);
events_init(&guider_ui);
custom_init(&guider_ui);
}
5.在LVGL界面用户接口函数aic_ui_init添加如下自定义用户界面代码。这里铺展使用命令宏形式进行灵活选择配置。
图5:添加用户界面
6,脚本编写。这里涉及到第3步源码植入脚本路径及宏的加入,另一部分是可配置命令脚本。
(1)源码植入脚本SConscript 。这里可以从其他示例界面工程拷贝,然后修改依赖宏,如下图所示。然后将此SConscript脚本拷贝到app_user_ui文件夹下每个子文件夹下。
图6:修改脚本并在设计界面目录下拷贝
(2)在路径application/Kconfig文件里添加如下:
图7:修改添加工程命令配置脚本
7.使用scons --menuconfig命令到LVGL,可以看到自创的界面配置单,可以选择使用自定义界面,非常方面灵活。
图8:自定义界面配置
8.这时自定义界面代码基本植入完成,可以开始编译。这个会出现一些编译不过问题。一个是LVGL API函数不匹配报错,一般替换SDK LVGL的API即可。另一个是SRAM_S0溢出报错如下,这时配置到PSRAM即可。
图9:SRAM_S0溢出报错
自此,用户自定义LVGL Demo界面移植基本完成。
三.测验
编译烧录后,开机后界面如下,成功植入自定义LVGL demo界面,且后面也很方面根据需要局部替换生成代码即可。
效果视频如下
[localvideo]92faeee7ddd752b1288eabad996f3dab[/localvideo]
-
发表了主题帖:
【匠芯创D133CBS】--5.触摸功能测试
本帖最后由 dirty 于 2024-8-31 23:20 编辑
本篇主要讲开发板显示屏触摸功能,并进行组织、编写测试该功能。
一.了解原理
开发板使用电容触摸屏(CTP),触摸驱动IC GT911,其支持五点触摸。下面了解硬件原理。
图:触摸引脚定义
I2C2_SCL--PA8
I2C2_SDA--PA9
RST -- PA10
INT --PA11
二.代码准备
1.scons --menuconfig配置引脚并使能
图2:配置触摸引脚
2.使能触摸驱动测试命令
图3:使能触摸驱动测试命令
3.触摸驱动测试需关闭LVGL Demo,用scons --menuconfig配置命令禁能会有编译不过问题,这里在SDK代码里测试触摸功能屏蔽掉LVGL系统初始化功能,这样不会带来编译问题同时不使用LVGL.
图4:关闭LVGL功能
4.测试触摸功能函数,查找打开设备,注册事件回调,创建信号量及任务,通过MSH_CMD_EXPORT导入测试命令函数
图5:触摸功能代码
图6:触摸测试打印与触摸驱动源码及配置
三.测试
1.编译烧录,串口输入命令list device,可以找到gt911设备,日志如下
图7:命令查询gt911设备
2.输入命令test_gt911启动触摸测试功能,手指在屏幕上触摸,可以看到如下日志
图8:触摸测试
可看到触摸信息有点轨迹ID,做多支持5个(0-4),点宽度,X坐标,Y坐标和接收数据时间戳。
至此,对开发板触摸功能有一个直观且较系统全面的了解,为后面奠定良好基础。
- 2024-08-25
-
发表了主题帖:
《人工智能实践教程》--神经网络
本篇主讲神经网络,涉及感知机、激活函数、计算图、CNN等,以笔记与实践形式展开。
感知机是最早的监督式学习算法,是神经网络和支持向量机的基础。感知机接收多个输入信号,输出一个信号。
神经网络由输入层、中间层、输出层结构组成。与感知机不同是多输入多输出。
激活函数是连接感知机和神经网络的桥梁。神经网络使用的激活函数有 :Sigmoid函数;阶跃函数;ReLU函数。
神经网络实现:先定义一些符号,如定义权重、神经元及输入层神经元等。在此上各层信号实现传递
下面用神经网络进行手写数字识别,分别介绍MNIST 数据集、神经网络的推理处理和批处理。过程步骤为:装数据,构建神经网络,训练网络及可视化。
MNIST数据集由从0到9的数字图像构成。MNIST数据集的一般使用方法是,先用训练图像进行学习,再用学习到的模型衡量能多大程度地对测试图像进行正确的分类。
import torch
from torch import nn
from torch.nn import functional as F
from torch import optim
import torchvision
from matplotlib import pyplot as plot
from utils import plot_image, plot_curve, one_hot, save_data
# step1 装数据
batch_size = 512
# step1. load dataset
train_loader = torch.utils.data.DataLoader(
torchvision.datasets.MNIST('mnist_data', train=True, download=True,
transform=torchvision.transforms.Compose([
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(
(0.1307,), (0.3081,))
])),
batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(
torchvision.datasets.MNIST('mnist_data/', train=False, download=True,
transform=torchvision.transforms.Compose([
torchvision.transforms.ToTensor(),
torchvision.transforms.Normalize(
(0.1307,), (0.3081,))
])),
batch_size=batch_size, shuffle=False)
x,y = next(iter(train_loader))
print(x.shape,y.shape,x.min(),y.min())
# plot_image(x,y,'sample')
# step2 构建神经网络
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# xw+b
self.fc1 = nn.Linear(28*28, 256)
self.fc2 = nn.Linear(256, 64)
self.fc3 = nn.Linear(64, 10)
def forward(self, x):
# x: [b, 1, 28, 28]
# h1 = relu(xw1+b1)
x = F.relu(self.fc1(x))
# h2 = relu(h1w2+b2)
x = F.relu(self.fc2(x))
# h3 = h2w3+b3
x = self.fc3(x)
return x
def backward(self, x):
# x: [b, 1, 28, 28]
# h1 = relu(xw1+b1)
x = F.relu(self.fc1(x))
# h2 = relu(h1w2+b2)
x = F.relu(self.fc2(x))
# h3 = h2w3+b3
x = self.fc3(x)
return x
# step3 训练网络
net = Net()
optimizer = optim.SGD(net.parameters(), lr=0.01, momentum=0.9)
train_loss = []
for epoch in range(10):
for idx,(x,y) in enumerate(train_loader):
x = x.view(x.size(0),28*28)
# =>[b,10]
out = net(x)
y_onehot = one_hot(y)
loss = F.mse_loss(out,y_onehot)
optimizer.zero_grad()
loss.backward()
optimizer.step()
train_loss.append(loss.item())
if idx %10 ==0:
print(epoch,idx,loss.item())
# step4 可视化显示
save_data(train_loss,'train_loss.csv')
plot_curve(train_loss)
total_correct = 0
for x,y in test_loader:
x = x.view(x.size(0),28*28)
out = net(x)
pred = out.argmax(dim = 1)
correct = pred.eq(y).sum().float().item()
total_correct+=correct
total_num = len(test_loader.dataset)
acc = total_correct / total_num
print("acuccy",acc)
x,y = next(iter(test_loader))
out = net(x.view(x.size(0),28*28))
pred = out.argmax(dim = 1)
plot_image(x,pred,"test")
仿真运行,第一次会下载MNIST数据集,随后生成可视化训练迭代损失曲线,可以看到是下降趋势,并将数据保存到train_loss.csv文件。
图1:训练迭代损失曲线
图2:测试手写数字识别结果
可以看到仿真在从0到9一直比对完,然后打印出了准确率。对数字识别很直观。
计算图可以将计算过程用图形表示,图形指数据结构图,由多节点和边表示。链式法则的定义如下;如果某个函数由复合函数表示,那么其导数可以用构成复合函数的各个函数的导数的乘积表示。将计算图的思路应用于神经网络,把构成神经网络的层作为一个类进行实现。首先,实现对应于激活函数的 ReLU 层和 Sigmoid 层。
神经网络的训练目的是找到使损失函数的值尽可能小的参数。寻找最优参数的过程称为最优化(Optimization)。在梯度下降算法中,将参数的梯度(导数)作为线索,沿梯度方向更新参数,并不断重复这个步骤,直到找到最优参数,这个过程称为随机梯度下降(Stochastic Gradient Descent,SGD)。
卷积神经网络(Convolutional Neural Network,CNN)。CNN 可用于图像识别、语音识别等场合。CNN 中包含了新的卷积层(Convolution层)和池化层(Pooling层)。卷积层进行卷积运算,卷积运算相当于图像处理中的“滤波器运算”。卷积层有填充、步幅的概念。在进行卷积层的处理前,有时要向输入数据的四周填入固定的数据(比如0等),这称为填充(padding),填充在卷积运算中经常会用到。应用波器的位置间隔称为步幅(stride).
在神经网络的实现中,卷积运算也可以进行批处理,实现处理的高效化。池化是一种缩小高、宽方向上的空间的运算。
神经网络部分设计的理论知识比较多,也有比较多的概念与数学公式,更多的学习在于积累与实践,多思考归纳总结勤动手,常读常新,会有很多新的收获。
- 2024-08-22
-
回复了主题帖:
【颁奖】全能小网关|CH32V208: BLE5.3+ USB2.0+ 10M Ethernet+ CAN + 4*UART
已确认个人收件信息
- 2024-08-17
-
回复了主题帖:
【匠芯创D133CBS】--4.PWM驱动蜂鸣器
秦天qintian0303 发表于 2024-8-17 19:28
开发板蜂鸣器是有源的还是无源的 ?
无源
-
发表了主题帖:
《人工智能实践教程》--机器学习-聚类与线性回归
本帖最后由 dirty 于 2024-8-17 16:24 编辑
本篇讲述机器学习,通过阅读学习笔记,更进一步理解机器学习。本书代码可通过Git 获取。
机器学习分类:监督式学习、非监督式学习、半监督式学习、强化学习、
机器学习常用算法:回归算法、基于实例算法、正则化算法、决策树算法、贝叶斯算法 、基于核的算法、聚类算法、关联规则学习算法、降低维度算法、集成算法。
数据预处理过程:清理、格式化、采样、分解、缩放。
主成分分析(PrincipalComponentAnalysis,PCA)是一种统计方法。通过正交变将一组可能存在相关性的变量转换为一组互不相关的变量,转换后的这组变量称为主成分。PCA是一种降维统计方法,它通过正交变换,将分量相关的原始变量转换为分量不相关的新变量。
聚类,是指将具有相似特征的庞杂对象自动归类到一起,形成一个簇,簇内的对象越相似,聚类的效果越好。它是一种非监督式学习方法,无须预先标注好训练数据。聚类与分类最大的区别就是分类的对象是事先已知的,而聚类的对象是未知的。
K-Means 算法是常用的聚类算法中的“相似度”,是利用距离作为评价指标来衡量的,即通过对象与对象之间的距离远近来判断它们是否属于同一类,也就是说,是否属于同一个簇。K-Means 是最经典、最实用、最简单的聚类算法的代表,K-Means 是一种用于发现给定数据集的K个簇的聚类算法,称其为 K-Means 是因为在发现的K个簇(数据点的集合,簇中的对象是相似的)中,每个的中心都对应该簇中数据的均值。簇的个数K是用户指定的,每个通过其质心(centroid),即簇中所有数据点的中心来描述。K-Means算法代码如下
import numpy as np
import matplotlib.pyplot as plt
# 载入数据
data = np.genfromtxt("kmeans.txt", delimiter=" ")
plt.scatter(data[:,0],data[:,1])
plt.rcParams['font.sans-serif']=['SimHei']
plt.title("载入数据")
plt.show()
print(data.shape)
# # 训练模型
# 计算距离
def euclDistance(vector1, vector2):
return np.sqrt(sum((vector2 - vector1)**2))
# 初始化质心
def initCentroids(data, k):
numSamples, dim = data.shape
# k个质心,列数跟样本的列数一样
centroids = np.zeros((k, dim))
# 随机选出k个质心
for i in range(k):
# 随机选取一个样本的索引
index = int(np.random.uniform(0, numSamples))
# 作为初始化的质心
centroids[i, :] = data[index, :]
return centroids
# 传入数据集和k的值
def kmeans(data, k):
# 计算样本个数
numSamples = data.shape[0]
# 样本的属性,第一列保存该样本属于哪个簇,第二列保存该样本跟它所属簇的误差
clusterData = np.array(np.zeros((numSamples, 2)))
# 决定质心是否要改变的变量
clusterChanged = True
# 初始化质心
centroids = initCentroids(data, k)
while clusterChanged:
clusterChanged = False
# 循环每一个样本
for i in range(numSamples):
# 最小距离
minDist = 100000.0
# 定义样本所属的簇
minIndex = 0
# 循环计算每一个质心与该样本的距离
for j in range(k):
# 循环每一个质心和样本,计算距离
distance = euclDistance(centroids[j, :], data[i, :])
# 如果计算的距离小于最小距离,则更新最小距离
if distance < minDist:
minDist = distance
# 更新最小距离
clusterData[i, 1] = minDist
# 更新样本所属的簇
minIndex = j
# 如果样本的所属的簇发生了变化
if clusterData[i, 0] != minIndex:
# 质心要重新计算
clusterChanged = True
# 更新样本的簇
clusterData[i, 0] = minIndex
# 更新质心
for j in range(k):
# 获取第j个簇所有的样本所在的索引
cluster_index = np.nonzero(clusterData[:, 0] == j)
# 第j个簇所有的样本点
pointsInCluster = data[cluster_index]
# 计算质心
centroids[j, :] = np.mean(pointsInCluster, axis = 0)
# showCluster(data, k, centroids, clusterData)
return centroids, clusterData
# 显示结果
def showCluster(data, k, centroids, clusterData):
numSamples, dim = data.shape
if dim != 2:
print("dimension of your data is not 完整例子!")
return 1
# 用不同颜色形状来表示各个类别
mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr']
if k > len(mark):
print("Your k is too large!")
return 1
# 画样本点
for i in range(numSamples):
markIndex = int(clusterData[i, 0])
plt.plot(data[i, 0], data[i, 1], mark[markIndex])
# 用不同颜色形状来表示各个类别
mark = ['*r', '*b', '*g', '*k', '^b', '+b', 'sb', 'db', '<b', 'pb']
# 画质心点
for i in range(k):
plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 20)
plt.rcParams['font.sans-serif']=['SimHei']
plt.title("显示结果")
plt.show()
# 设置k值,聚类的个数
k = 4
# centroids 簇的中心点
# cluster Data样本的属性,第一列保存该样本属于哪个簇,第二列保存该样本跟它所属簇的误差
centroids, clusterData = kmeans(data, k)
if np.isnan(centroids).any():
print('Error')
else:
print('cluster complete!')
# 显示结果
showCluster(data, k, centroids, clusterData)
print(centroids)
# 做预测
x_test = [0,1]
np.tile(x_test,(k,1))
# 误差
np.tile(x_test,(k,1))-centroids
# 误差平方
(np.tile(x_test,(k,1))-centroids)**2
# 误差平方和
((np.tile(x_test,(k,1))-centroids)**2).sum(axis=1)
# 最小值所在的索引号
np.argmin(((np.tile(x_test,(k,1))-centroids)**2).sum(axis=1))
def predict(datas):
return np.array([np.argmin(((np.tile(data,(k,1))-centroids)**2).sum(axis=1)) for data in datas])
# # 画出簇的作用区域
# 获取数据值所在的范围
x_min, x_max = data[:, 0].min() - 1, data[:, 0].max() + 1
y_min, y_max = data[:, 1].min() - 1, data[:, 1].max() + 1
# 生成网格矩阵
xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.02),
np.arange(y_min, y_max, 0.02))
z = predict(np.c_[xx.ravel(), yy.ravel()])# ravel与flatten类似,多维数据转一维。flatten不会改变原始数据,ravel会改变原始数据
z = z.reshape(xx.shape)
# 等高线图
cs = plt.contourf(xx, yy, z)
# 显示结果
showCluster(data, k, centroids, clusterData)
仿真结果如下:
图1:K-Means 算法仿真
线性回归以一个坐标系中的一个维度为结果,其他维度为特征(如在二维平面坐标系中,以纵轴为结果,横轴为特征)。如果将无数的样本点放在坐标系中,发现它们是围绕着一条直线分布的(类似方程y=kx+b),那么可以采用线性回归进行分析。线性回归的目的,就是寻找一条直线最大程度地“拟合”样本特征和样本输出标记之间的关系。只有一个样本特征的线性回归,,为简单线性回归。如下是一个简单线性回归算法实例
import numpy as np
import matplotlib.pyplot as plt
x = np.array([1., 2., 3., 4., 5.])
y = np.array([1., 3., 2., 3., 5.])
plt.scatter(x, y)
plt.axis([0, 6, 0, 6])
plt.show()
x_mean = np.mean(x)
y_mean = np.mean(y)
num = 0.0
d = 0.0
for x_i, y_i in zip(x, y):
num += (x_i - x_mean) * (y_i - y_mean)
d += (x_i - x_mean) ** 2
a = num/d
b = y_mean - a * x_mean
y_hat = a * x + b
plt.scatter(x, y)
plt.plot(x, y_hat, color='r')
plt.axis([0, 6, 0, 6])
plt.show()
x_predict = 6
y_predict = a * x_predict + b
print(y_predict)
图2:线性回归
通过学习了解了机器学习的概念和基础知识,并演示了K-Means 算法和线性回归算法,对机器学习算法有了进一步认识。