N维数组举例
N维数组是机器学习和神经网络的主要数据结构。
0-d(标量) 1.0 一个类别
1-d(向量) [1.0, 2.7, 3.4] 一个特征向量
2-d(矩阵) 一个样本-特征矩阵
3-d RGB图片(宽×高×通道)
4-d 一个RGB图片(批量大小×宽×高×通道)
5-d 一个视频批量(批量大小×时间×宽×高×通道)
os.chdir()
用于改变当前工作目录到指定的路径。
os.chdir(path)
-
path -- 要切换到的新路径。如果允许访问返回 True , 否则返回False。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os, sys
path = "/tmp"
# 查看当前工作目录
retval = os.getcwd()
print "当前工作目录为 %s" % retval
# 修改当前工作目录
os.chdir( path )
# 查看修改后的工作目录
retval = os.getcwd()
print "目录修改成功 %s" % retval
os.listdir()
用于返回指定的文件夹包含的文件或文件夹的名字的列表。它不包括 . 和 .. 即使它在文件夹中。
os.listdir(path)
-
path -- 需要列出的目录路径。 返回指定路径下的文件和文件夹列表。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import os, sys
# 打开文件
path = "/var/www/html/"
dirs = os.listdir( path )
# 输出所有文件和文件夹。但不包含子文件夹里的文件夹和文件,
# 并按照目录树结构的排序输出结果,即深度优先。
for file in dirs:
print (file)
append()
append()函数类似于尾插,就是给元素后面追加一个字符串.
Python中[m : ] 、[:n] [-1]、[ : -1]、[::-1]、[2::-1]和[1:]意义说明
[m : ] 代表列表中的第m+1项到最后一项
[ : n] 代表列表中的第一项到第n项
import numpy as np
a=[1,2,3.4,5]
print(a)
[ 1 2 3 4 5 ]
print(a[-1]) 取最后一个元素
结果:[5]
print(a[:-1]) 除了最后一个取全部
结果:[ 1 2 3 4 ]
print(a[::-1]) 取从后向前(相反)的元素
结果:[ 5 4 3 2 1 ]
print(a[2::-1]) 取从下标为2的元素翻转读取
结果:[ 3 2 1 ]
print(a[1:]) 取第二个到最后一个元素
原文链接:Python中[m : ] 、[:n] [-1]、[ : -1]、[::-1]、[2::-1]和[1:]意义说明_zaf赵的博客-优快云博客
x[..., 0] 、x[..., 1]、x[:,:,0]含义
先随机产生一个[3,4,5]的numpy数组。则该x维度是3,shape是(3,4,5),总共包含60个元素。
x[:,:,0] 意思是对数组x切片,可以想象成一个正方体数据,每次切下一个面的数据。第二维取0则得出来[3,4]大小的数组,即
首先...只能出现一次,就是说你可以,[ : , : , : ],但是[ ... , ...]就会报错。
使用了 ... 之后,数字0不再是元素的index 了 , 而是 轴(axis)。下面通过numpy.amax()(选出轴最大的元素)来具体说明。
首先看axis=2,第一个数字189是从x[ ][ ] [0] 到 x[ ][ ] [4] 比较而得,因此一共有3*4=12元素
axis=1,第一个数字99是从x[ ][0] [ ] 到 x[ ][3] [ ] 比较而得,因此一共有3*5=15元素
同理,axis=0,第二个数字189是从x[0] [ ] [ ] 到 x[2] [ ] [ ] 比较而得,因此一共有4*5=20元素
axis=0时 比较的示意图:
最直观的:函数所选的axis的值,就表明 x[ ][ ][ ] 的第几个方块号,从0开始,代表第一个[ ],即x[ ] [ ] [ ],所以维度与axis的对应关系为,对于维度为(3,4,5)的数组,axis=0 长度为3,axis=1长度为4,axis=2长度为5。
则[...,0]表示,与[:,:,0]等价:
原文链接:https://blog.youkuaiyun.com/qq_39237205/article/details/124201701
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
在python 中,通过 os.environ 获取环境变量
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '0' #默认值,输出所有信息
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '1' #屏蔽通知信息(INFO)
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' #屏蔽通知信息和警告信息(INFO\WARNING)
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' #屏蔽通知信息、警告信息和报错信(INFO\WARNING\FATAL)
常见信息等级 INFO(通知)<WARNING(警告)<ERROR(错误)<FATAL(致命信息)
利用os.environ设置使用cpu和GPU
os.environ[“CUDA_DEVICE_ORDER”] = “PCI_BUS_ID” # 按照PCI_BUS_ID顺序从0开始排列GPU设备
os.environ[“CUDA_VISIBLE_DEVICES”] = “0” #设置当前使用的GPU设备仅为0号设备 设备名称为'/gpu:0'
os.environ[“CUDA_VISIBLE_DEVICES”] = “1” #设置当前使用的GPU设备仅为1号设备 设备名称为'/gpu:0'
os.environ[“CUDA_VISIBLE_DEVICES”] = “0,1” #设置当前使用的GPU设备为0,1号两个设备,名称依次为'/gpu:0'、'/gpu:1'
os.environ[“CUDA_VISIBLE_DEVICES”] = “1,0” #设置当前使用的GPU设备为1,0号两个设备,名称依次为'/gpu:0'、'/gpu:1'。表示优先使用1号设备,然后使用0号设备。
原文链接:https://blog.youkuaiyun.com/Jamesjjjjj/article/details/83414680
如何设置cpu,等于-1表示禁用GPU,即默认使用cpu
import os
os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
convolution layers
nn.Conv2d:对由多个输入平面组成的输入信号进行二维卷积
从整体上来看:
Conv2d是一个类,它包含了做卷积运算所需要的参数(__init__函数),以及卷积操作(forward函数)。
再来看一下它的详细参数:
torch.nn.Conv2d(in_channels,
out_channels,
kernel_size,
stride=1,
padding=0,
dilation=1,
groups=1,
bias=True,
padding_mode='zeros')
一共九个参数,一般用前三个就可以处理一般的任务:
in_channels :输入通道数目
out_channels :输出通道数目
kernel_size :卷积核大小,如果输入是一个值,比如 3 ,那么卷积核大小就是 3 × 3 ,如果不想卷积核宽和高相等,还可以输入tuple类型数据,比如: ( 3 , 5 )
stride :步长大小,跟上面卷积核参数一样,如果输入是一个值,比如 2 ,步长就是 2 × 2 \times ,还可以输入元组 ( 2 , 1 ) ,表示卷积核每次向右移动 1 个步长,向下移动 2 个步长。
padding :填充,参数表示在周围补0的情况。补0的方向为上、下、左、右四个方向。如果是输入是单个值,比如1,就是在上下左右四个方向补一圈0。如果输入是元组比如 (2,1) ,表示在上下两个方向各补两行0,在左右两个方向各补一列0。
dilation :进行扩展卷积需要的参数。
groups :进行分组卷积需要的参数。
bias :偏置,布尔类型,默认为 True ,即增加一个学习的偏置项。
padding_mode :填充的模式,默认是 zero ,还可以选择 reflect 、 replicate 、 circular
关于卷积核的解释:
这里的卷积核参数只是指定卷积核的宽度和高度,对于多通道的卷积,代码内部会根据输入通道数初始化对应的卷积核数目,即:如果输入是3通道,那么就会有三个我们指定宽高的卷积核做相应的卷积操作。
关于步长的解释:
步长指的是卷积核在输入矩阵的上每次移动几步。移动方向由两个,向右或者向下。分别由两个值指定。
关于填充的解释:
填充的主要目的是为了充分利用输入图片的边缘信息。
关于扩张(dilation)参数的解释:
本质上就是扩大卷积核,比如将 3 × 3 3 \times 33×3 的扩大为 7 × 7 7 \times 77×7 的,然后对扩大的部分用0进行填充,
目的是扩大感受野,捕获多尺度上下文信息。
关于输入通道数 in_channels
和输出通道数 out_channels
的解释:
如果卷积核输入的是原始的图片,那么我们可以根据图片类型决定图片的输入通道数,如果是RGB图片, in_channels=3
,如果是灰度图像,in_channels=1
。输出通道数需要我们自己指定,具体指定多少需要根据经验。
图像形状的变化规则
举例
import torch
import torch.nn as nn
# in_channels=16, out_channels=33, kernel_size=(3, 5)
m = nn.Conv2d(16, 33, (3, 5), stride=(2, 1), padding=(4, 2), dilation=(3, 1))
print(m)
# 我们随机构造输入数据
# N=20, C_in=16, H_in=50, W_in=100
# 对应上面说的 (N, C, H, W)
input = torch.randn(20, 16, 50, 100)
output = m(input)
print(output.shape)
结果
Conv2d(16, 33, kernel_size=(3, 5), stride=(2, 1), padding=(4, 2), dilation=(3, 1))
torch.Size([20, 33, 26, 100])
计算过程
如何理解卷积神经网络中的通道(channel)_Medlen的博客-优快云博客_卷积神经网络通道数
这里输入通道数是3,每个通道都需要跟一个卷积核做卷积运算,然后将结果相加得到一个特征图的输出,这里有4个过滤器,因此得到4个特征图的输出,输出通道数为4。
再来看一下单通道的例子:
输入是灰色图片,输入通道数是1,卷积核有3个,做三次卷积操作,生成3个特征图,输出通道数为3。
单通道特征图的计算为:
【卷积核的大小一般为奇数*奇数】 1*1,3*3,5*5,7*7都是最常见的。这是为什么呢?为什么没有偶数*偶数?
(1)更容易padding
在卷积时,我们有时候需要卷积前后的尺寸不变。这时候我们就需要用到padding。假设图像的大小,也就是被卷积对象的大小为n*n,卷积核大小为k*k,padding的幅度设为(k-1)/2时,卷积后的输出就为(n-k+2*((k-1)/2))/1+1=n,即卷积输出为n*n,保证了卷积前后尺寸不变。但是如果k是偶数的话,(k-1)/2就不是整数了。
(2)更容易找到卷积锚点
在CNN中,进行卷积操作时一般会以卷积核模块的一个位置为基准进行滑动,这个基准通常就是卷积核模块的中心。若卷积核为奇数,卷积锚点很好找,自然就是卷积模块中心,但如果卷积核是偶数,这时候就没有办法确定了,让谁是锚点似乎都不怎么好。
torch中tensor的view函数
目的是将多维的的数据如(none,36,2,2)平铺为一维如(none,144)
import numpy as np
import torch
x = torch.Tensor(2, 2, 2)
y = x.view(1, 8) #输出维度:1*8
z = x.view(-1, 4) # -1表示维数自动判断,此输出的维度为:2*4
t = x.view(8) #输出维度 : 8*1
t = x.view(-1) #输出维度: 1*8
python中的glob介绍-文件名模式匹配
提供了一个函数用于从目录通配符搜索中生成文件列表,不用遍历整个目录判断每个文件是不是符合。
1、通配符
星号(*)匹配零个或多个字符
import glob
for name in glob.glob('dir/*'):
print (name)
复制代码
dir/file.txt
dir/file1.txt
dir/file2.txt
dir/filea.txt
dir/fileb.txt
dir/subdir
复制代码
列出子目录中的文件,必须在模式中包括子目录名:
复制代码
import glob
#用子目录查询文件
print ('Named explicitly:')
for name in glob.glob('dir/subdir/*'):
print ('\t', name)
#用通配符* 代替子目录名
print ('Named with wildcard:')
for name in glob.glob('dir/*/*'):
print ('\t', name)
复制代码
Named explicitly:
dir/subdir/subfile.txt
Named with wildcard:
dir/subdir/subfile.txt
2、单个字符通配符
用问号(?)匹配任何单个的字符。
import glob
for name in glob.glob('dir/file?.txt'):
print (name)
dir/file1.txt
dir/file2.txt
dir/filea.txt
dir/fileb.txt
3、字符范围
当需要匹配一个特定的字符,可以使用一个范围
import glob
for name in glob.glob('dir/*[0-9].*'):
print (name)
dir/file1.txt
dir/file2.txt
python基础之import模块导入和包的调用
import ...
语句from ... import ...
语句:Python 的 from 语句让你从模块中导入一个指定的部分到当前命名空间中。小心与自定义的对象重名,导致被覆盖掉了。from ... import *
语句:导入模块中定义的全部公有名称。这种声明不要过多地使用,可读性极差,而且导入了过多不必要的对象。不过,有时会与 __all__
一起使用,此时,会一次性导入 __all__
变量中列出的所有模块。
包
包是一个分层次的文件目录结构,它定义了一个由模块及子包,和子包下的子包等组成的 Python 的应用环境。
简单的说,包就是文件夹,但该文件夹下必须存在 __init__.py
文件, 该文件的内容可以为空,也可以有 Python 代码,原则是尽量保持 __init__.py
文件的精简。__init__.py
用于标识当前文件夹是一个包。若这个文件不存在,那么这个目录只是一个目录而不是一个包。有如下目录的 m3.py、test1.py
├─root
│ ├─pack1
│ │ ├─pack2
│ │ │ ├─pack3
│ │ │ │ ├─__init__.py
│ │ │ │ ├─m3.py
│ │ ├─__init__.py
│ │ ├─m2.py
│ ├─test1.py
# m3.py
def pack3_print():
print("我是m3!")
pack_3 中的 __init__.py
文件中为空,m3.py 有一个打印函数 pack3_print()
。由于调用包的其他模块所在的绝对路径是千变万化的,所以在包的内部调用自身其他文件中的函数、常量、类,应该使用相对路径,而不是绝对路径。
1.现在若要在 test1.py
文件夹调用这个函数,可以这么做:
1)按照路径导入即可:
from root.pack1.pack2.pack3.m3 import pack3_print
pack3_print()
or
import pack1.pack2.pack3.m3
pack1.pack2.pack3.m3.pack3_print()
2)在 test1.py 同级目录的 pack1 的文件夹下创建一个 __init__.py
文件, 文件内容是:
from .pack2.pack3.m3 import pack3_print
再在 test1.py 中引入 pack3_print 函数:
from pack1 import pack3_print
pack3_print()
from . import <some-module>
句法表示相对导入。语句中的 . 表示当前包。还有 from .. import <some-module>
,这里的 .. 表示当前包的上一层。
包内部的文件之间互相导入可以使用相对导入,并且通过提前把函数、常量、类导入到 __init__.py
中后,包外面再想导入这些内容时,就可以直接用 from 包名 import 函数名
导入了,可以精简代码。
2.我们再在 pack2 下创建一个 m2.py 文件,在 m2 中调用 pack3_print 函数:
# 在 m2.py 使用相对路径直接导入:
from .pack2.pack3.m3 import pack3_print
def pack2_print():
print('我是m2!')
pack3_print()
不过,由于前面我们已经在 __init__.py
导入过 pack3_print 函数了,所以,我们可以在 m2 中这样直接导入:
from . import pack3_print -- 注意一下循环导入依赖的问题?
我们再修改上面的 __init__.py
,把 pack2_print
函数导入进去:
from .pack2.pack3.m3 import pack3_print
from .m2 import pack2_print
最后,在 test1.py
中调用这个 pack2_print
函数:
from pack1 import pack3_print
from pack1 import pack2_print
pack3_print()
pack2_print()
文件操作
open()--打开
file = open(file_name [, mode='r' [ , buffering=-1 [ , encoding = None ]]])
此格式中,用[]
括起来的部分为可选参数,即可以使用也可以缺省。
file:表示要创建的文件对象。
file_name:要创建或打开文件的文件名称,该名称要用引号(单引号或双引号都可以)括起来。需要注意的是,如果要打开的文件和当前执行的代码文件位于同一目录,则直接写文件名即可;否则,此参数需要指定打开文件所在的完整路径。
mode:可选参数,用于指定文件的打开模式。如果不写,则默认以只读(r)模式打开文件。
buffering:可选参数,用于指定对文件做读写操作时,是否使用缓冲区(通常使用缓冲区,建议不需要修改 buffing 参数的值)。
encoding:手动设定打开文件时所使用的编码格式,不同平台的encoding参数值也不同,以Windows为例,其默认为cp936(实际上就是 GBK 编码)。
文件对象读取
1、file.read()
为了读取一个文件的内容,调用file.read([size]), 这将读取一定数目的数据, 然后作为字符串或字节对象返回。size是一个可选的数字类型的参数。 当 size被忽略了或者为负, 那么该文件的所有内容都将被读取并且返回。
如果文件是以文本模式(非二进制模式)打开的,则read()函数会逐个字符进行读取;反之,如果文件以二进制模式打开,则read()函数会逐个字节进行读取。
2、file.readline()
file.readline()
会从文件中读取单独的一行。对于读取以文本格式打开的文件,读取一行很好理解;对于读取以二进制格式打开的文件,它们会以“\n”
作为读取一行的标志。file.readline()
如果返回一个空字符串, 说明已经已经读取到最后一行.
3 flie.readlines()
readlines()
函数用于读取文件中的所有行,它和调用不指定size
参数的read()
函数类似,只不过该函数返回是一个字符串列表,其中每个元素为文件中的一行内容。
4 file.write()
f.write(string)
将string
写入到文件中, 然后返回写入的字符数。
Python
的文件对象中,不仅提供了write()
函数,还提供了writelines()
函数,可以实现将字符串列表写入文件中。
5 file.close
打开的文件一定要关闭,否则程序的运行会出现意想不到的问题。
为了更好地避免此类问题,不同的编程语言都引入了不同的机制。在Python中,对应的解决方式是使用with as语句操作上下文管理器(context manager),它能够帮助我们自动分配并且释放资源。
使用with as操作已经打开的文件对象(本身就是上下文管理器),无论期间是否抛出异常,都能保证with as语句执行完毕后自动关闭已经打开的文件。
with open('myfile.txt', 'r') as f:
read_data = f.read()
os模块提供的与目录相关的函数
os.path(osp.)模块提供的与目录相关的函数
pickle模块--dumps() loads() dump() load()
Python中有个序列化过程叫作pickle,它能够实现任意对象与文本之间的相互转化,也可以实现任意对象与二进制之间的相互转化。也就是说,pickle可以实现 Python对象的存储及恢复。
pickle模块提供了以下 4 个函数供我们使用:
dumps():将 Python 中的对象序列化成二进制对象,并返回;
loads():读取给定的二进制对象数据,并将其转换为 Python 对象;
dump():将 Python 中的对象序列化成二进制对象,并写入文件;
load():读取指定的序列化数据文件,并返回对象。
以上这 4 个函数可以分成两类,其中dumps和loads实现基于内存的 Python 对象与二进制互转;dump和load实现基于文件的 Python 对象与二进制互转。
读写JSON文件
如果希望把一个列表或者一个字典中的数据保存到文件中又该怎么做呢?答案是将数据以JSON格式进行保存。JSON是JavaScript Object Notation的缩写,它本来是JavaScript语言中创建对象的一种字面量语法,现在已经被广泛的应用于跨平台跨语言的数据交换,原因很简单,因为JSON也是纯文本,任何系统任何编程语言处理纯文本都是没有问题的。
json
模块主要有四个比较重要的函数,分别是:
- dump - 将Python对象按照JSON格式序列化到文件中
- dumps - 将Python对象处理成JSON格式的字符串
- load - 将文件中的JSON数据反序列化成对象
- loads - 将字符串的内容反序列化成Python对象
# Python中的json模块就可以将字典或列表以JSON格式保存到文件中,代码如下所示。
import json
mydict = {
'name': 'carpediem',
'age': 38,
'qq': 957658,
'friends': ['Tom', 'David'],
'cars': [
{'brand': 'BYD', 'max_speed': 180},
{'brand': 'Audi', 'max_speed': 280},
{'brand': 'Benz', 'max_speed': 320}
]
}
try:
with open('data.json', 'w', encoding='utf-8') as fs:
json.dump(mydict, fs)
except IOError as e:
print(e)
print('保存数据完成!')
参考链接:Python基础篇(八)-- 文件操作_长路漫漫2021的博客-优快云博客_python实验文件操作
nn.Linear()函数
它是一个线性变换函数
通常作为全连接层(fc),可固定输出通道数。
格式:
nn.Linear(in_features, out_features, bias=True)
其中,in_features为输入样本的大小,out_features为输出样本的大小,bias默认为true。如果设置bias = false那么该层将不会学习一个加性偏差。
import torch
x = torch.randn(8, 3) # 输入样本
fc = torch.nn.Linear(3, 5)
output = fc(x)
print('fc.weight.shape:\n ', fc.weight.shape, fc.weight)
print('fc.bias.shape:\n', fc.bias.shape)
print('output.shape:\n', output.shape)
ans = torch.mm(x, torch.t(fc.weight)) + fc.bias # 计算结果与fc(x)相同
print('ans.shape:\n', ans.shape)
print(torch.equal(ans, output))
输出
fc.weight.shape:
torch.Size([5, 3]) Parameter containing:
tensor([[-0.1878, -0.2082, 0.4506],
[ 0.3230, 0.3543, 0.3187],
[-0.0993, -0.0028, -0.1001],
[-0.0479, 0.3248, -0.4867],
[ 0.0574, 0.0451, 0.1525]], requires_grad=True)
fc.bias.shape:
torch.Size([5])
output.shape:
torch.Size([8, 5])
ans.shape:
torch.Size([8, 5])
True
Process finished with exit code 0
注:
首先,nn.linear(3,5)其权重的shape为(5,3),
所以x与其相乘时,用torch.t求了nn.linear的转置,
这样(83)(35)得到全连接层后的输出维度(85),
结果也与fc(x)验证是一致的, torch.mm就是数学上的两个矩阵 相乘。
torch.nn.Linear()函数_人类高质量算法工程师的博客-优快云博客_torch.nn.linear
F.softmax()和F.log_softmax函数
F.softmax作用:按照行或者列来做归一化的
F.softmax函数语言格式:
# 0是对列做归一化,1是对行做归一化
F.softmax(x,dim=1) 或者 F.softmax(x,dim=0)
F.log_softmax作用:
在softmax的结果上再做多一次log运算
F.log_softmax函数语言格式:
F.log_softmax(x,dim=1) 或者 F.log_softmax(x,dim=0)
参数解释
-
x指的是输入矩阵。
-
dim指的是归一化的方式,如果为0是对列做归一化,1是对行做归一化
import torch
import torch.nn.functional as F
logits = torch.rand(2,2)
pred = F.softmax(logits, dim=1)
pred1 = F.log_softmax(logits, dim=1)
print(logits)
print(pred)
print(pred1)
Pytorch学习笔记(七):F.softmax()和F.log_softmax函数详解_ZZY_dl的博客-优快云博客_f.softmax函数
sum的使用语法
sum(iterable[, start])
-
iterable -- 可迭代对象,如:列表、元组、集合。
-
start -- 指定相加的参数,如果没有设置这个值,默认为0。
例如:sum([1,2,3])的结果是6
sum((2, 3, 4), 1)
的结果是10,表示元组求和后再加上1.
sum([0,1,2,3,4], 2)
的结果是12,表示列表求和后再加上2.
keepdims=True---保持原数组的维度
sum(1)、sum(0)
用途:求数组每一行的和,等价于 sum(axis=1)
用途:求数组每一列的和,等价于sum(axis=0)
>>> import numpy as np
>>> x = np.array([[0, 1], [1, 1], [2, 2]])
>>> x.sum(1)
array([1, 2, 4])
>>> x.sum(-1)
array([1, 2, 4])
>>> x.sum(axis=1)
array([1, 2, 4])
>>> print(x,axis=1)
>>>x.sum(0)
array[3,4]
原文链接:https://blog.youkuaiyun.com/maple05/article/details/107943144
def __call__()
在 Python 中提供了__call__ 方法,允许创建可调用的对象(实例class)。如果类中实现了 __call__ 方法,则可以像使用函数一样使用类。
# 当class中没有__call__方法时,该实例不能像函数一样被调用,会报错,如下
class TestCall():
def test_func(self):
print "test"
f = TestCall()
f()
# 执行结果
Traceback (most recent call last):
File "/Users/test_pytest/aaa_pytest.py", line 18, in <module>
f()
AttributeError: TestCall instance has no __call__ method
类中存在__call__()方法,对象f通过__call__(self, *args, **kwargs)方法可以模拟函数行为。
举例
class MyForm(Form):
name = StringField('Name', [InputRequired(), length(max=50)])
length(max=5)就是返回了个_length函数,wtform调用校验器的时候实际上就是这样调用的:
class Length(object):
def __init__(self, min=-1, max=-1, message=None):
self.min = min
self.max = max
if not message:
message = u'Field must be between %i and %i characters long.' % (min, max)
self.message = message
def __call__(self, form, field):
l = field.data and len(field.data) or 0
if l < self.min or self.max != -1 and l > self.max:
raise ValidationError(self.message)
class MyForm(Form):
name = StringField('Name', [InputRequired(), Length(max=50)])
首先实例化这个校验器Length(max=50), 这时返回的是对象实例,然后我们定义了方法__call__方法,说明实例对象是可以调用的, 最后的结果就是Length(max=50)(form, field)。
def __repr__()
_repr__() 是 Python 类中的一个特殊方法,由 object 对象提供,由于所有类都是 object 类的子类,所以所有类都会继承该方法。
该方法主要实现 “自我描述” 功能——当直接打印类的实例化对象时,系统将会自动调用该方法,输出对象的自我描述信息,用来告诉外界对象具有的状态信息。
但是,object 类提供的 __repr__() 方法总是返回一个对象(类名 + obejct at + 内存地址),这个值并不能真正实现自我描述的功能!如下:
class Person():
def __init__(self,name,age):
self.name = name
self.age = age
person = Person('zk', 20)
print(person)
print(person.__repr__())
输出
<__main__.Person object at 0x7f5fe2bb4e50>
<__main__.Person object at 0x7f5fe2bb4e50>
如果你想在自定义类中实现 “自我描述” 的功能,那么必须重写 repr 方法:
class Person():
def __init__(self,name,age):
self.name = name
self.age = age
def __repr__(self):
return 'Person类,有name和age两个属性'
person = Person('zk', 20)
print(person)
print(person.__repr__())
输出
Person类,有name和age两个属性
Person类,有name和age两个属性
https://blog.youkuaiyun.com/weixin_45594025/article/details/121425343
np.arange()
函数返回一个有终点和起点的固定步长的排列,默认起点为0
np.random.choice
从中随机抽取元素
numpy.random.choice(a, size=None, replace=True, p=None)
从a(只要是ndarray都可以,但必须是一维的)中随机抽取数字,并组成指定大小(size)的数组
replace:True表示可以取相同数字,False表示不可以取相同数字
数组p:与数组a相对应,表示取数组a中每个元素的概率,默认为选取每个元素的概率相同。
np.random.choice(5,3)
在[0, 5)内输出五个数字并组成一维数组(ndarray) #相当于np.random.randint(0, 5, 3)
输出:array([1, 4, 1])
numpy.diff(a, n=1,axis=-1)
沿着指定轴计算第N维的离散差值
参数:
a:输入矩阵
n:可选,代表要执行几次差值
axis:默认是最后一个
举例数组中a[n]-a[n-1]
import numpy as np
a=np.array([1, 6, 7, 8, 12])
diff_x1 = np.diff(a)
print("diff_x1",diff_x1)
# diff_x1 [5 1 1 4]
# [6-1,7-6,8-7,12-8]
二维数组
b=np.array([[1, 6, 7, 8, 12],[1, 6, 7, 8, 12]])
diff_x2 = np.diff(b)
print("diff_x2 \n",diff_x2)
# diff_x2
# [[5 1 1 4]
# [5 1 1 4]]
numpy.random.uniform()介绍:
-
函数原型: numpy.random.uniform(low,high,size)
功能:从一个均匀分布[low,high)中随机采样,注意定义域是左闭右开,即包含low,不包含high.
-
参数介绍:
low: 采样下界,float类型,默认值为0;
high: 采样上界,float类型,默认值为1;
size: 输出样本数目,为int或元组(tuple)类型,例如,size=(m,n,k), 则输出 m * n * k 个样本,缺省时输出1个值。返回值:ndarray类型,其形状和参数size中描述一致。
-
这里顺便说下ndarray类型,表示一个N维数组对象,其有一个shape(表维度大小)和dtype(说明数组数据类型的对象),使用zeros和ones函数可以创建数据全0或全1的数组,原型:
numpy.ones(shape,dtype=None,order=‘C’)
其中,shape表数组形状(m*n), dtype表类型, order表是以C还是fortran形式存放数据。
- 类似uniform,还有以下随机数产生函数:
- randint:
原型:numpy.random.randint(low, high=None, size=None, dtype=‘l’),产生随机整数; - random_integers: 原型: numpy.random.random_integers(low, high=None, size=None),在闭区间上产生随机整数;
- random_sample:
原型: numpy.random.random_sample(size=None),在[0.0,1.0)上随机采样; - random:
原型: numpy.random.random(size=None),和random_sample一样,是random_sample的别名; - rand:
原型: numpy.random.rand(d0, d1, …, dn),产生d0 - d1 - … - dn形状的在[0,1)上均匀分布的float型数。 - randn:
原型:numpy.random.randn(d0,d1,…,dn),产生d0 - d1 - … - dn形状的标准正态分布的float型数。
np.round
有时候我们要对浮点数取整,numpy的round()函数就是这样一个工具。
一般该函数遵循四舍五入原则
但是需要特别注意的是,当整数部分以0结束时,round函数一律是向下取整。
zip()
用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表或者字典。
zip()可以传2个参数,只要是序列就可以(列表、元组、字符串)
print(zip(("a","b","c"),(1,2,3)))
print(list(zip(("a","b","c"),(1,2,3))))
print(list(zip(("a","b","c"),(1,2,3,4))))
print(list(zip(("a","b","c","d"),(1,2,3))))
输出结果
<zip object at 0x0216EB98>
[('a', 1), ('b', 2), ('c', 3)]
[('a', 1), ('b', 2), ('c', 3)]
[('a', 1), ('b', 2), ('c', 3)]
分析:第一行输出的是zip的对象,要转换为列表用list的方法
zip的左右两个参数序列是一一对应的关系,如果有多的自动忽略
例子2
p={'name':'nicholas','age':18,'gender':'man'}
print(list(zip(p.keys(),p.values())))
输出结果
[('name', 'nicholas'), ('age', 18), ('gender', 'man')]
分析:这样就可以把字典中的元素提取出来
例子
print(dict(zip(("a","b","c"),(1,2,3))))
输出结果
{'a': 1, 'b': 2, 'c': 3}
分析:这里可以直接将zip对象转为字典。
注意:定义神经网络, 需要继承 nn.Moudle, 并重载 __init__ 和 forward 方法