Faster R-CNN代码详解 标注数据形状

Faster R-CNN代码实战–潘登同学的深度学习笔记

文章目录

*
Faster R-CNN代码实战–潘登同学的深度学习笔记
* 数据集介绍
* 数据处理
*
先看combined_roidb
RoIDataLayer
get_output_dir
* Trian过程
*
create_architecture

+ build_network
+
* Build head
* Build RPN
*
回到_anchor_component
* 回到Build RPN
*
接一层3*3卷积,再接一层1*1卷积
* Build proposals
*
_proposal_layer
_anchor_target_layer
_proposal_target_layer
* build_predictions
+ 回到build_network
回到create_architecture

+ _add_losses
* 回到Train

数据集介绍

采用的数据集是 VOCDevkit2007/VOC2007

Faster R-CNN代码详解 标注数据形状
  • Annotation: XML文件,是给图像打框的标注数据
    Faster R-CNN代码详解 标注数据形状
  • ImageSets: 图片的编号及属性
    Faster R-CNN代码详解 标注数据形状
  • JPEGImages: 存储图片
    Faster R-CNN代码详解 标注数据形状
  • 下面的用不上,那些是做语义分割的…以后再说

; 数据处理

Faster R-CNN代码详解 标注数据形状

先看combined_roidb

Faster R-CNN代码详解 标注数据形状

其中get_roidb会调用数据集里面写好的API的调用方法,这里就直接当成人家弄好的拿来用即可,看一看API给出的数据长啥样

  • roidb
    Faster R-CNN代码详解 标注数据形状
  • imdb
    Faster R-CNN代码详解 标注数据形状

; RoIDataLayer

在这里RoIDataLayer主要是打乱顺序,这里没用打乱顺序; 而后面这个RoIDataLayer的数据是专门喂给Fast R-CNN,去训练Fast R-CNN,所以这里初始化的时候,只要了roidb的数据

Faster R-CNN代码详解 标注数据形状

get_output_dir

get_output_dir主要是把预训练好的VGG保存起来,后面拿来用

Trian过程

Faster R-CNN代码详解 标注数据形状

前面的没啥看的,关键是这句 layers = self.net.create_architecture(sess, "TRAIN", self.imdb.num_classes, tag='default')

; create_architecture

Faster R-CNN代码详解 标注数据形状

前面的也不关键,关键是这句 self.build_network(sess, training)

build_network

Faster R-CNN代码详解 标注数据形状

; Build head

这里就是构建了一个VGG16网络而已

Faster R-CNN代码详解 标注数据形状

Build RPN

这里就是构建RPN网络了

Faster R-CNN代码详解 标注数据形状

核心讲一下这里的数据形状,因为tf的tensor是静态结构,没有数据传进来就看不见大小,这里模拟一下…

假设一开始拿来的图片大小是shape=(333,500,3) 索引号为1807

1. forward

因为在Train的时候,会调用RoIDataLayer的forward方法,先看forward方法

Faster R-CNN代码详解 标注数据形状

1.1 进_get_next_minibatch中

Faster R-CNN代码详解 标注数据形状

1.1.1 _get_next_minibatch_inds方法,获得小批量数据的索引

Faster R-CNN代码详解 标注数据形状

1.1.2 get_minibatch方法

Faster R-CNN代码详解 标注数据形状

1.1.2.1 核心是_get_image_blob

Faster R-CNN代码详解 标注数据形状

其中一个if判断主要是判断数据增强,因为这里用的是水平增强,所以要将图片水平翻转

其中关键是 prep_im_for_blob方法生成图片与缩放图片的比例

1.1.2.1.1 prep_im_for_blob

将图片缩放成要求的 (600,1000) 这里主要是将短边缩放为600,然后长边跟随变化,超过了就剪切掉,没超过就不管,与原论文有些许不同

Faster R-CNN代码详解 标注数据形状

回到 1.1.2 get_minibatch方法

  • im_scale: 对图片的缩放比例 1.8
  • blobs[‘data’]: 是一个批次的图片(就是一张)缩放后的做了均值归一后的 shape=(600,901)
  • blobs[‘gt_boxes’]: 是一个二维数组,shape=(K,5) 前四列放的是缩放后的坐标值,第五列放的是框的类别号
  • blobs[‘im_info’]: 是一个一维数组前两个是图片的宽和长后一个是缩放比例, [600,901,1.8]

回到 create_architecture,前面三行就是接受刚才forward导出的数据

Faster R-CNN代码详解 标注数据形状
; 回到_anchor_component

Faster R-CNN代码详解 标注数据形状
  • Height=600/16=38
  • Weight=901/16=57
    38*57对应的就是Bottom的面积(即VGG出来的Feature Map的大小)

tf.py_func函数

这个函数的作用就是能将tensor的运算转为numpy的运算,方便地改变tensor,核心操作函数是里面的generate_anchors_pre

2.1 generate_anchors_pre

Faster R-CNN代码详解 标注数据形状

2.1.1 generate_anchors

generate_anchors函数是由原作者写的

Faster R-CNN代码详解 标注数据形状

主要就是生成那Anchor对应的九个Anchor boxes,要强调的是: Anchor boxes是跟着Anchor走的,而Anchor是Featrue Map上的一个像素, 只要Anchor不变Anchor boxes,至于后面的Predict boxes要向ground truth靠近,那是将Anchor boxes进行了平移(相当于复制了一份,再拿去train),Anchor boxes是不变的

这个函数中的生成的 anchors实际上是每个 Anchor boxes的左上角与右下角的 相对坐标

array([[ -83.,  -39.,  100.,   56.],
      [-175.,  -87.,  192.,  104.],
      [-359., -183.,  376.,  200.],
      [ -55.,  -55.,   72.,   72.],
      [-119., -119.,  136.,  136.],
      [-247., -247.,  264.,  264.],
      [ -35.,  -79.,   52.,   96.],
      [ -79., -167.,   96.,  184.],
      [-167., -343.,  184.,  360.]])

2.1.2 shifts

shifts是由Anchor中心坐标构成的shape=(K,4)(K=3857=2166)的数组,其实只要shape=(K,2)就能描述Anchor中心坐标的位置,而之所以要四个,是为了让 Anchor boxes*的左上角与右下角相对坐标能直接与shifts运算变成绝对坐标

Faster R-CNN代码详解 标注数据形状

最后2166个Anchor与9个Anchor boxes进行相关运算,再reshape成(2166*9=19494),总共就有19494个框(与论文中的2万个差不多)

回到Build RPN

Faster R-CNN代码详解 标注数据形状
; 接一层33卷积,再接一层11卷积
  • net –> 3*3卷积
  • (1,38,57,512)
  • 1*1卷积
  • rpn_cls_score(1,38,57,18)
  • _reshape_layer
  • (1,18,38,57)
  • (1,2,513,38)
  • rpn_cls_score_reshape(1,513,38,2)
  • _softmax_layer
  • (19494,2)
  • (1,513,38,2)
  • _reshape_layer
  • (1,2,513,38)
  • (1,18,57,38)
  • rpn_cls_prob(1,57,38,18)
  • 1*1卷积
  • (1,38,57,51)
  • rpn_bbox_pred(1,38,57,36)

Faster R-CNN代码详解 标注数据形状

Build proposals

Faster R-CNN代码详解 标注数据形状

核心是三句

  • _proposal_layer 相当于预测,给后面的ROI pooling去使用的候选框
  • _anchor_target_layer 给RPN网络准备正负例的
  • _proposal_target_layer
; _proposal_layer

Faster R-CNN代码详解 标注数据形状

3.1 proposal_layer

Faster R-CNN代码详解 标注数据形状
  • pre_nms_topN: 12000
  • post_nms_topN: 2000
  • nms_thresh: 0.7
  • im_info: 600
  • scores: (19494,1), 就是前面的 rpn_cls_prob(1,57,38,18)取了第四维的后九个,因为正例prob往往越高,所以排在后面,这里就是把正例取出来,后面reshape成(19494,1)
  • rpn_bbox_pred: (19494,4), 将 rpn_bbox_pred(1,38,57,36)reshape成(19494,4)

3.1.1 bbox_transform_inv

  • 传进去的anchor在前面shifts中说到是shape(19494,4)代表原图上19494个框对应的4个坐标,是论文中的带下角标a a a的x , y , w , h x,y,w,h x ,y ,w ,h
    Faster R-CNN代码详解 标注数据形状
  • 传进去的rpn_bbox_pred: (19494,4)代表预测的框的位置,(理应是)是论文中的x , y , w , h x,y,w,h x ,y ,w ,h,但是这里略有不同,这里的rpn_bbox_pred是预测值与原Anchor boxes的偏移量,我们知道,预测既可以直接预测值,也可以预测残差,这里就相当于预测残差
  • 函数输出的就是论文中的x , y , w , h x,y,w,h x ,y ,w ,h

Faster R-CNN代码详解 标注数据形状

3.1.2 clip_boxes

clip_boxes就是对预测的框进行剪切了,大于原图的就不要了

Faster R-CNN代码详解 标注数据形状

3.1.3 NMS

这个在之前看论文的时候说过,就不再赘述

Faster R-CNN代码详解 标注数据形状

3.1.4 其他

剩下就是将NMS之后的框,控制在post_nms_topN范围内,要是多了就去掉分数低的,少了就不管

  • rois = 返回值blob: 第一列为batch的索引号,后四列为筛选出来框的位置坐标
  • roi_scores = 返回值scores: 框的scores
_anchor_target_layer

Faster R-CNN代码详解 标注数据形状

4.1 anchor_target_layer

这个函数也是原作者写的…

Faster R-CNN代码详解 标注数据形状
  • rpn_cls_score: (1,38,57,18) 是未经过softmax变换的Z值
  • all_anchors: shifts中产生的所有框
  • A: 9
  • total_anchors: 19494
  • K: 2166
  • im_info: 600
  • height: 38
  • width: 57

先是将所有超出图的框给去掉(可以通过_allowed_border来控制超出多少是可以忍受的)

注意: 为什么不在一开始生成anchor boxes的时候就把他给去掉,而是在处理样本的时候才去掉?

是因为在真正用的时候,可能在图片的边边角角有物体,这时候只需要对框进行裁剪就可以,而gt训练集的ground truth永远是在图里面的,不可能超出图,所以要把训练集的超出图的框给去掉

接着就是标注 label: 1 is positive, 0 is negative, -1 is dont care

对上面过滤剩下的Anchor与ground truth计算重叠度,因为bbox_overlaps函数被反复调用,调用量很大,作者将其编译为了C,又转成了pyd,看不见,但是不难理解这个函数,其实就是计算IOU的

  • overlaps: 二维数组(N,W) N表示ROI的数量,W表示GT的数量,里面装的就是IOU
  • argmax_overlaps: 一维数组(N,) 表示候选框与哪个GT的IOU最大,里面装的是GT的索引号
  • max_overlaps: 一维数组(N,) 与argmax_overlaps有关,argmax_overlaps装的是索引号,这里装的是IOU值,两个一一对应
  • gt_argmax_overlaps:一维数组(W,) 表示与GT重叠度最大的那个候选框的索引号
  • gt_max_overlaps: 一维数组(W,) 与gt_argmax_overlaps有关,这里装的是IOU值
  • gt_argmax_overlaps: 重新搜索一遍,因为可能存在这样一种情况,就是 overlaps.argmax(axis=0)得到的只有一个值,但是可能最大的两个值相等,那 argmax只会返回第一次出现的索引号,重新搜索一遍找出所有gt_max_overlaps相等的那些候选框,所以gt_argmax_overlaps最后的形状可能会大于W

接下来就是真正标准数据集了

  • 相关划分参数
    Faster R-CNN代码详解 标注数据形状
  • rpn_batchsize: 256,其中128为正例,128为负例

从上往下进行:

  • max_overlaps小于0.3的候选框被划分为负例
  • gt_argmax_overlaps的所有都被划分为正例
  • max_overlaps大于0.7的候选框被划分成正例
  • 随机选择128的正例,128个负例,多余的将label赋值为-1

4.1.1 _compute_targets

Faster R-CNN代码详解 标注数据形状

_compute_targets方法的主要作用是: 计算每个Anchor boxes与他们最接近的那个GT的位置到底相差多远

4.1.1.1 bbox_transform

Faster R-CNN代码详解 标注数据形状

这里就可以对应回论文的t x ∗ , t y ∗ , t w ∗ , t h ∗ t_x^,t_y^,t_w^,t_h^t x ∗​,t y ∗​,t w ∗​,t h ∗​

Faster R-CNN代码详解 标注数据形状

最后是把t x ∗ , t y ∗ , t w ∗ , t h ∗ t_x^,t_y^,t_w^,t_h^t x ∗​,t y ∗​,t w ∗​,t h ∗​按行摆放,得到的 target shape(少于19494,4)(因为输入的ex_rois是过滤过的)

所以回到 4.1 anchor_target_layer

  • bbox_targets: (少于19494,4) 过滤后的anchor boxes的t x ∗ , t y ∗ , t w ∗ , t h ∗ t_x^,t_y^,t_w^,t_h^t x ∗​,t y ∗​,t w ∗​,t h ∗​按行摆放
  • bbox_inside_weights: (少于19494,4) 过滤后的anchor boxes的权重,如果是labels为1,则那4的那个维度的数值为(1,1,1,1),否则为(0,0,0,0)
  • bbox_outside_weights: (少于19494,4) 对应回原文中求loss的1 N r e g \frac{1}{N_{reg}}N r e g ​1 ​,所有都一样无论正负例,都是正例数量的倒数,即1 n l a b e l = 1 \frac{1}{n_{label=1}}n l a b e l =1 ​1 ​
    Faster R-CNN代码详解 标注数据形状

4.1.2 _unmap

_unmap函数的作用就是将刚刚操作的少于19494的框,还原成19494,因为真正训练的时候,打的框还是19494,只不过我们不想用那些出界的框,现在还原回去,label照旧设置成-1,对结果也不影响

Faster R-CNN代码详解 标注数据形状
  • labels: (19494,)
  • bbox_targets: (19494,4)
  • bbox_inside_weights: (19494,4)
  • bbox_outside_weights: (19494,4)

回到 4.1 anchor_target_layer

  • rpn_labels: (1,1,938,57) 将labels(-1,) 先reshape成(1,38,57,9)再reshape成(1,9,38,57)再reshape成(1,1,938,57)
  • rpn_bbox_targets: (1,38,57,94) 将bbox_targets(19494,4) reshape成(1,38,57,94)
  • rpn_bbox_inside_weights: (1,38,57,9*4)
  • bbox_outside_weights: (1,38,57,9*4)
; _proposal_target_layer

_proposal_target_layer是给最终的Fast RCNN准备正负例样本的, 在执行_proposal_target_layer前先等待_anchor_target_layer执行结束可能是因为_anchor_target_layer里面用着bbox_overlaps,而这个函数也要用bbox_overlaps,所以避免GPU爆炸吧…

输入(NMS之后的框,控制在post_nms_topN范围)

  • rois: (2000,5)第一列为batch的索引号,后四列为筛选出来框的位置坐标
  • roi_scores: (2000,1)框的得分scores

Faster R-CNN代码详解 标注数据形状

5.1 proposal_target_layer

Faster R-CNN代码详解 标注数据形状
  • all_rois: rois(2000,5)第一列为batch的索引号,后四列为筛选出来框的位置坐标
  • all_scores: roi_scores: (2000,1)框的得分scores
  • if cfg.FLAGS.proposal_use_gt是想确定一下是否直接把GT用于训练,这里是False,那就不管
  • num_images: 1
  • rois_per_image: 256
  • fg_rois_per_image: 64

5.1.1 _sample_rois

_sample_rois函数是主要是生成roi及相关scores及框的最终调整位置

Faster R-CNN代码详解 标注数据形状
  • overlaps: (2000,W) W是GT的数量
  • gt_assignment: (2000,) 表示ROI与哪个GT的IOU最大,里面装的是GT的索引号
  • max_overlaps: (2000,) 表示ROI与最大IOU的GT的IOU,里面装的是IOU的值
  • gt_boxes=blobs['gt_boxes']: (W,5) 前四列表示GT的坐标,后一列表示类别号
  • labels: (2000,) 表示ROI最可能属于哪一类
  • fg_inds: 一维数组 表示max_overlaps中的IOU大于0.5的那些ROI的索引号
  • bg_inds: 一维数组 表示max_overlaps中的IOU小于0.5但大于0.1的那些ROI的索引号
  • 接着的逻辑判断,就是确保正负例到达要求… 总共有256, 正例为64个,剩下的为负例
  • keep_inds: 将正负例的索引号组成列表(正例在前,负例在后)
  • labels = labels[keep_inds] 对labels进行过滤 过滤后的形状为(256,1)
  • labels[int(fg_rois_per_image):] = 0: 把负例标记为0
  • rois: 正负例的框的坐标
  • roi_scores: 正负例的框的scores
  • bbox_target_data: (256,5) 第一列的是label 后四列就是targets(往下看)
  • bbox_targets: (256,84)相当于将每一个类别的框的位置做了一个One-hot编码,属于第k类的框只会在[4k,4k+4]的位置有坐标值
  • bbox_inside_weights: 就是一个在[4k,4k+4]的位置(1.0, 1.0, 1.0, 1.0)的数组

5.1.1.1 _compute_targets

gt_boxes[gt_assignment[keep_inds], :4]的作用是形成与正负例形状一样的GT的坐标,因为在计算loss的时候一个正例需要与其对应的GT框进行匹配来计算偏移量…

Faster R-CNN代码详解 标注数据形状

这个函数虽然跟前面的_compute_targets名字一样,但是具体方面还是有所不同,估计是作者忘记改名了吧

Faster R-CNN代码详解 标注数据形状
  • ex_rois: (256,4) 256的正负例的坐标
  • gt_rois: (256,4) 256的正负例最接近的的GT的坐标
  • labels: (256,1)
  • targets: bbox_transform前面说过这个方法,出来的是 target shape(256,4)
  • 最后返回一个: (256,5) 第一列的是label 后四列就是targets

5.1.1.2 _get_bbox_regression_labels

Faster R-CNN代码详解 标注数据形状
  • bbox_target_data: (256,5) 第一列的是label 后四列就是targets(往下看)
  • num_classes: 21
  • bbox_targets: (256,84) 相当于将每一个类别的框的位置做了一个One-hot编码,属于第k类的框只会在[4k,4k+4]的位置有坐标值
  • bbox_inside_weights: 就是一个在[4k,4k+4]的位置(1.0, 1.0, 1.0, 1.0)的数组

回到_proposal_target_layer

  • rois: (256,5)
  • roi_scores: (256,)
  • labels: (256,)
  • bbox_targets: (256,21*4)
  • bbox_inside_weights: (256,21*4)
  • bbox_outside_weights: (256,21*4)

build_predictions

Faster R-CNN代码详解 标注数据形状
  • 一层ROI池化层
  • 一层展平
  • 两层全连接
  • 一层Output层
  • cls_score: softmax前的Z值
  • cls_prob: softmax之后的概率值
  • 另一层Output层
  • bbox_prediction: 没有激活函数的线性变换

; 回到build_network

后面就是将预测与得分等信息挂到net上

回到create_architecture

_add_losses

_add_losses方法就是将四个loss合并成一个loss(在这里是整体训练的,不像论文中是分开训练的,但是论文也说了可以整体训练,甚至论文中的loss与这里的loss就是一样的)

Faster R-CNN代码详解 标注数据形状

; 回到Train

最难搞的create_architecture已经搞定了,后面就是常规流程了,只不过这里写的比较友好,各种打印保存等等,就不再细聊了…

记得要将文件放在没有中文路径的文件夹下…

Faster R-CNN代码详解 标注数据形状
Faster R-CNN代码详解 标注数据形状
Faster R-CNN代码详解 标注数据形状

Original: https://blog.csdn.net/weixin_52185313/article/details/124329642
Author: PD我是你的真爱粉
Title: Faster R-CNN代码详解 标注数据形状

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/681235/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 什么是物联网?定义和解释

    什么是物联网? 物联网(IoT)是一个相互关联的计算设备系统,无需人工输入即可通过无线网络收集和传输数据。 ​这不仅仅是笔记本电脑和智能手机:几乎所有带有开/关开关的东西都可能连接…

    人工智能 2023年7月27日
    071
  • UpdatePack7R2 v22.11.10 Win7累积更新离线整合补丁

    这是个Windows 7 更新补丁安装包,Win7累积更新离线安装包,它包括所有关键更新和安全更新及Internet Explorer所有版本的更新,此外还集成了NVMe驱动和US…

    人工智能 2023年6月30日
    069
  • 全连接神经网络(DNN)

    最近想要学习深度学习模型,没有一上来就先学习CNN、RNN、LSTM,而是先学习全连接神经网络(Fully Connected Neural Network),原因非常简单,上述所…

    人工智能 2023年7月13日
    0192
  • neo4j导入实体,neo4j导入关系

    neo4j可以使用csv文件导入数据,可以快速导入大量的数据形成图谱 一、导入实体 先创建一个csv文件,给里面添加数据,如下图添加了name和birthday数据。 将文件用编辑…

    人工智能 2023年6月1日
    083
  • 动手做个 AI 机器人,帮我回消息

    大家好,我是鱼皮,自从做了知识分享,我的微信就没消停过,平均每天会收到几百个消息,大部分都是学编程的朋友向我咨询编程问题。 但毕竟我只有一个人,没法所有消息都一个个回复,所以也是很…

    人工智能 2023年7月26日
    066
  • MXNe

    MXNet问题解决方案 详细介绍 MXNet是一种用于构建深度学习模型的开源框架。它提供了一种灵活且高效的方式来构建、训练和部署深度学习模型。在解决机器学习问题时,MXNet提供了…

    人工智能 2023年12月31日
    035
  • YOLOv5的head详解

    YOLOv5的head详解 在前两篇文章中我们对YOLO的backbone和neck进行了详尽的解读,如果有小伙伴没看这里贴一下传送门:YOLOv5的Backbone设计YOLOv…

    人工智能 2023年6月17日
    0138
  • 计算机视觉-图像的傅里叶变换

    😊😊😊 欢迎来到本博客😊😊😊本次博客内容将继续讲解关于OpenCV的相关知识🎉 作者简介:⭐️⭐️⭐️ 目前计算机研究生在读。主要研究方向是人工智能和群智能算法方向。目前熟悉pyt…

    人工智能 2023年7月29日
    068
  • 适用于遥感图像处理的神经网络

    图像解译-影像解译,又称为判读或判译,指从图像获取信息的基本过程。即根据各专业(部门)的要求,运用记忆标志和实践经验与知识,从遥感影像上识别目标,定性、定量地提取出目标的分布、结构…

    人工智能 2023年6月20日
    0156
  • 基于python的图像识别

    基于python的图像识别 图像识别364 图像识别391 这里图像识别,涉及到python3.9.1和python3.6.4。之所以着重提及python版本,是因为代码使用了te…

    人工智能 2023年5月23日
    072
  • 【youcans 的 OpenCV 例程200篇】178.图像分割之 GrabCut 图割法(框选前景)

    【youcans 的 OpenCV 例程200篇】176.图像分割之均值漂移算法【youcans 的 OpenCV 例程200篇】177.图像分割之 GraphCuts 图割法【y…

    人工智能 2023年6月22日
    098
  • Pandas知识点-详解分组函数groupby

    Pandas知识点-详解分组函数groupby 在数据分析时,经常需要将数据分成不同的群组,pandas中的groupby()函数可以完美地完成各种分组操作。分组是根据DataFr…

    人工智能 2023年7月6日
    097
  • 【CUDA安装详细教程】

    目录 前言 一、cuda的下载及安装 * 1.cuda版本 2.CUDA toolkit Download 3.cuda安装 二、cuDNN下载及安装 * 1.cuDNN下载 2….

    人工智能 2023年6月12日
    0162
  • 【虚拟主播】刚刚,我用三行代码创建了一个虚拟主播

    刚刚,我花了10分钟,写了三行代码创建一个具有明星脸的虚拟主播 先看看效果: 一个简单的虚拟数字人的实现非常简单,需要调用三个模型: [En] The implementation…

    人工智能 2023年5月27日
    072
  • 数字图像处理——实验一 离散傅里叶变换(代码)

    clc;clear;close all;a=imread(‘Lena512C.bmp’);f=rgb2gray(a); %原图为三维图像,转为二维图像 fi…

    人工智能 2023年6月20日
    075
  • 电脑生成siri语音_语音识别和语音合成技术

    语音识别是指将一个人的声音转换成相应的文本,这需要计算机自动识别语音信号中的单词和单词,甚至理解其中包含的含义。语音识别有着广泛的应用,包括语音拨号、语音导航、设备操作控制、语音文…

    人工智能 2023年5月27日
    067
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球