【Python学习笔记】cs231nPython Numpy教程
回顾经典教程cs231n,完成assignments觉得很困难,感觉自己python基础语法掌握的不是很熟,就顺藤摸瓜找了cs231n他们的官方Python个Numpy教程
如果对英文原版上手有困难,可以看这个:
b站同济子豪兄中文讲解的cs231n:【子豪兄】精讲CS231N斯坦福计算机视觉公开课(2020最新)
作业相关解析:CS231N作业详解零基础版
cs231n官方笔记:贺完结!CS231n官方笔记授权翻译总集篇发布
cs231nPython、Numpy入门教程:Python Numpy Tutorial (with Jupyter and Colab)
我的学习历程是:英文原版理解困难——>b站中文解析——>课后作业练习困难——>b站作业讲解——>官方教程补python和Numpy基础
真是基础不牢,地动山摇。就是因为我对Numpy不够熟悉,平时主要使用C#,python代码写的也不够多,所以啃作业很头疼。先得慢慢把基础的学会。
for循环遍历字典时,默认情况遍历的是字典的键(key)
遍历值value:for animal in d.values()
同时遍历键和值:for animal, legs in d.items()
存储不同数据类型——元组()、列表[]
存储相同数据类型——数组
无序——集合{}、字典{:},
有序——元组()、列表[]、数组
一段我第一次看没明白的程序:
字典是这样索引的
{(0,1):0}
{(1,2):1}
{(2,3):2}
{(3,4):3}
{(4,5):4}
{(5,6):5}
(5,6)这个整体作为键,对应的d[t]值也就是5
以及我觉得很别扭的self,之前做KNN作业的时候,被self.X_train迷惑了很久,想了半天这是哪来的变量
然后查了一下,这个self是类比C#里面的this,
(似乎C#很多时候都不写this.X_train=X,直接把this省去了?我以前写代码的时候很少写到this,但是印象里个别地方,特别是变量和函数参数一个名字的时候,不写this就容易出错)
还有一点很不适应的地方,是python中的数组和C#也不太一样,C#里输入几个[][]就能定义的数组,到了python里面变复杂了
我目前个人感觉python确实方便,但是很多时候太简略了,一个变量是从哪里开始定义并使用的我要找很久……C#全写在类开头,Awake()——OnEnable(0——Start()一套走下来很清晰,应该是我还没有完全上手Python的缘故。一些快速创建数组的方法:np.zeros创建全0数组,np.ones创建全1数组,np.full创建一个给定大小和类型并且以指定数字全部填充的新数组,np.eye创建对角线全为1的单位矩阵
发现一个不错的帖子参考:
np.empty() and np.full()
很奇怪为什么这里修改切出来的b,会影响a的值,查了以后发现切片相当于只是创建了一个视图,并没有复制一份a,所以修改子数组会在原数组的基础上进行修改。
感觉这个视图和引用有点像,但视图不一定是原数据的全部
想了很久为什么这里输出的是第二列
我总记不得要把行列分开看,找半天发现没有这个元素
折腾了一圈,还是print(a[a>2])最舒服
那如果我输入的数据类型和参数指定的数据类型不符,Numpy是报错还是自动转换呢?
基本数学函数对数组进行元素操作,既可以作为运算符重载,也可以作为numpy模块中的函数:加减乘除都是对应项直接操作,也可以调用Numpy函数
注意,与MATLAB不同,是元素乘法,而不是矩阵乘法。相反,我们使用点函数来计算向量的内积,将向量与矩阵相乘,dot既可以作为numpy模块中的函数,也可以作为数组对象的实例方法:
这点和C#应该是一样的,之前计算敌人可视范围的时候,cos就用的dot函数计算
乘法就是直接对应元素相乘,(x1,y1)和(x2,y2)相乘是(x1x2,y1y2)
向量点乘是(x1x2+y1y2),得到一个值
这个地方是很容易糊涂
矩阵和向量是每一行的x,y分别与向量相乘
[x1v1+y1v2,x2v1+y2*v2]
最后那个矩阵乘法,是第一行x第一列——结果的第一个元素,第一行x第二列——结果的第二个元素
看看基础教程还是有必要的,好多函数的用法跟我一眼脑补的不一样
如果不仔细看看文档,我会以为axis=0的意思是把第一列的数据加起来,但其实是把纵向的每一行相加
请注意,对秩(维度)为1的数组进行转置不会有任何作用
“广播
广播是一种强大的机制,允许numpy在执行算术运算时处理不同形状的数组。我们经常有一个较小的数组和一个较大的数组,并且我们希望多次使用较小的数组来对较大的数组执行一些操作。”
我接触过的C#里面的广播好像是用在观察者模式里面的,麦扣的教程中定义了IEndObserver接口,一旦玩家死亡,GameMangaer就通知所有实现接口的(敌人)对象,宣告玩家死亡,敌人胜利,播放胜利动画
相当于用tile函数堆叠成一行对一个,然后分别相加
Numpy广播允许我们在不实际创建v的多个副本的情况下执行此计算
所以这个广播的意思应该是,只需要一份数据,所有的都复用,广泛使用、传播的意思?而不是C#里面那种“通知”性质的广播
支持广播的功能被称为通用功能。您可以在文档中找到所有通用函数的列表。
Python函数:np.reshape()
结果确实是一样的,很神奇类似的函数(scipy。spatial。distance。cdist)计算两组点上所有对之间的距离;您可以在文档中阅读相关内容。
Matplotlib是一个打印库。在本节中,简要介绍matplotlib.pyplot模块,该模块提供了一个类似于MATLAB的绘图系统。
matplotlib中最重要的功能是绘图,它允许您绘制二维数据,可以理解成Python的可视化库
子模块
您可以使用subplot函数在同一个图形中绘制不同的东西。以下是一个示例:
相当于多张图组合到一起画
img_tinted对图片重新着色
#imshow的一个小问题是,如果数据不是uint8,它可能会给出奇怪的结果。为了解决这个问题,我们在显示图像之前将其显式地投射到uint8。
np.uint8()
CS231n作业详解零基础版笔记:
b站讲解链接
装Anaconda的时候要打勾(我就没装成功过这玩意,Jupyter Notebook照样用……)
//这个整除容易出错,**幂是两个星号,%取模
这里-3对2取模也等于1
整除和取模和乘除优先级相同
有的整数很长,需要更长的储存空间,int8不够装的话就需要int16、int32等。字符串又有单引号,又有双引号:字符里面可能会把字符串用单引号引用起来
如果单引号引用单引号,那就会报错,双引号引用双引号也会报错
可以双引号里面嵌套单引号,也可以反过来
注注释:#和前面的代码空两格,和自己后面空一格开始写,比较漂亮
#会被电脑忽略,而且只对一行有效
多行注释:6个单引号或者6个双引号,都是全英文这图好好笑,注释要素过多的后果和数学函数一样,有输入,有映射,有输出+
参数的调用顺序很重要多行注释的本质就是放了个字符串在这里None值用来判断(类似C#里面的if(null==xxxx?))
Print函数没有返回值,是开函数(?听译的,但问了一下chatGPT,并没有这个术语)
让a=print(-0.0261)的返回值,然后输出a,发现是None输入很长的数字时,如果用了逗号分隔,python会把他认成三个数,语法正确,但是格式不规范,也不是原本想表达的含义变量名可以包含中文,但是最好不要Python关键字是这种绿色加粗字体显示的,相当于Python已经将这些词占用,不能使用这些作为变量名赋值而这种紫色的@则是操作符,也不能使用
老师这讲的和我认知的不太一样,我记得驼峰命名法是attackTarget种大小写分割单词的写法,另一种写法是m_target,之前Unity架构课的老师经常用m_的这种。
搜了一下,我的理解是对的
(赞美Unity架构课老师,很注意代码命名细节)
这个input很像C#里面的inputField,生成一个等待输入的输入框,此处通过print再显示出来
除了有大于小于等于不等于以外,还有is not
Tab缩进,如果是空格缩进的话不知道用了几个,很容易出错
elif是else if的缩写老师的条件判断执行时卡死了,是加了个else的情况,但实际应该不是else的问题,可以只写if和elifIf,elif这种是执行了一种情况就不会继续了,类似switch case,如果每个流程都需要判断,统一使用if
如果加上else语句,整个判断模块至少会有一条被执行
向量只有一个维度,后面就是空的
传入的矩阵大小还是个元组
只有一个维度的时候,写不写括号和逗号都可以
Identity单位矩阵,zeros全0,ones全1
可以通过现有的矩阵复制维度,创建新矩阵相当于[0,2)
可以在创建矩阵的时候就指定数据类型
借用一下老师画的图,很清晰易懂
矩阵可以沿不同的轴向进行拼接
转置矩阵:
输入的参数也是元组逆转矩阵使用广播机制可以实现矩阵直接减去列向量,而不还用for循环
可以放回原矩阵去取值多个条件并举一定要用小括号括起来
Figure相当于画板,axes/subplot相当于画板上面的画纸
python matplotlib中axes与axis的区别是什么?
教程传送门
老师的例子里面有一个linspace函数:
python numpy 中linspace函数
教程传送门
需要注意避雷的问题:array改变,其复制值dup也会改变使用切片办法,但不总是有用,虽然id不一样了,但是改变array还是一起改变了dup
直接“=”是浅拷贝,指向的位置都是同一个地方
而deepcopy是复制了两份数据,其指向和id都不同了Numpy自带也有copy拷贝函数
三个有名的图像处理库:OpenCV、SkImage、PIL
这里因为out是img的浅拷贝,所以输出的时候原图也改变了
之前的img已经被破坏改色了,这里需要重新加载进来
很多时候浅拷贝会出现一些莫名其妙的问题,建议常用深拷贝排序默认是升序
线性代数相关,已知Ax=b,求x用Numpy内置函数可以直接实现最小二乘法
使用solve函数得到x另一个求x的方法是梯度下降
Ax永远不等于Y,但可以让Y-Ax尽可能小,趋近于0,这样其损失(代价)loss越小越好
X要加个“帽子”(xheight?/xhat?没听清楚)
要求最优解x,根据高数知识要求偏导数
已知dx,求梯度下降
使用Numpy的原因:比python自带的速度快
对于不太常用Python+Numpy编程的我来说,这个入门上手作业简直香,太有必要在做CS231n的作业之前先做CS131n打好基础了,不然直接冲CS231n根本无从下手。
CS131n入门作业:
导入本地文件里面,*表示所有函数
如果是下面这种,则是只导入一个函数
设置图片大小、最邻近插值、灰度图
%matplotlib Jupyter notebook特有的魔术命令
如果没有下面三行命令,修改了linalg.py和imageManip.py文件以后,需要重新run一下这一大段导入库、初始化的配置代码,但是有了这三行就不需要了,会自动重新加载。
第一题我用的中括号嵌套的方式做的定义矩阵
老师看到了M矩阵的特殊性,1-12的连续数,用了linspace函数+reshape
像老师额外构造的一个c,他就是只有一个维度的向量,和a有区别
第二题老师用的a.dot(b),本质上和np.dot(a,b)是一样的
很奇怪为什么我的结果是这样:有可能是向量没有转换为矩阵
np.dot()使用方法
使用教程
np.dot()函数用法
使用教程
经过检查,发现是我第一题的a写成了向量而不是矩阵,导致后面出错
把a改成矩阵以后就正确了
纠结了很久为什么不传参a的转置,而是直接传a,chatGPT回答说a这种只有一行的矩阵,转不转置没有区别
第二题我比老师多调用了一层dot_product函数
正确答案:
老师是计算了a和b的点积和M与a.T的点积之外就直接相乘了
题目的注意事项是所有的输入都必须是两个维度的,只有二维矩阵才能被转置,一维的不行
比如前面定义的这个c,转置与否是一样的效果
chatGPT这个写法也出错,目前我测试了的只有老师那种写法是对的
所以老师的方法相当于是矩阵先两两乘积然后再点积
a是一行三列矩阵,b是三行一列矩阵,a和b做矩阵乘法得到一行一列(1x1)的新矩阵
M是四行三列矩阵,a的转置是三行一列矩阵,M和a的转置做矩阵乘法得到四行一列(4x1)的新矩阵
最后把一行一列的新矩阵和四行一列的新矩阵做矩阵乘法得到四行一列的新矩阵