python 基础知识
深度学习部分的所有的python版本都要python >=3.8+ ,pytorch >=2.0
这里只讲解基本的python3的知识,用以在有其他编程语言的基础上,快速入门python3,然后使用
pytorch进行深度学习。
编程基础和输出
python的语法
python是靠缩进来显示层次结构的,注意空格和tab符是不同的缩进格式,
python注释的方式有2种:1是行首使用#
号,2是区块注释
'''
这里的代码不会被执行,这也是区块注释
'''
"""
这里的代码不会被执行
"""
输出变量的方法
print("hello world")
即可输出hello world
在print的括号里的开始指定字符f后跟双引号,这样可以解析双引号里的变量,变量需要使用大括号括住变量名。
name="zhangsan"
print(f"hello world, welcome {name}.")
变量类型
python有如下7种基本数据类型:
- 字符串
a=hello world
- 数值
- 整数型int
b=123
- 浮点型float
pi=3.1415926
常用的运算符
+ - * / #加减乘除
** 幂次方
() 括号
// 整除取商整数
% 整除取余数
- 布尔型
bool_v=True
- 字符串比较使用
==
或!=
- 数值比较,使用大于
>
,小于<
,等于==
,大于等于>=
,小于等于<=
,
注意判断是否相等是两个等号,一个等号是赋值。
set_v = {1,3,5}
print(3 in set_v)
print(2 not in set_v)
name_list={'zhangsan':12,'lisi':21,'zhaoliu':25}
print("zhangsan" in name_list)
print(12 in name_list.values())
变量之间的转换
#定义变量
str_v = '123'
int_v = 123
float_v = 123.0
bool_v = True
#转换变量为字符串
str(int_v)
str(bool_v)
#转换变量为整数型
int(str_v)
int(bool_v)
#转换变量为浮点型
float(int_v)
float(bool_v)
#转换为布尔型
bool(int_v)
bool(str_v)
#注意:其他变量转为布尔型时,只有当数字是0、字符串、集合、元组、列表、字典都为空时,结果才为False
#逻辑值转其他格式时,False是0,True是1.
集合
set_v = {1,2,3,4,2}
集合是无序、不可重复的元素的组合。使用大括号定义。元组
tuple_v=(1,3,6)
元组有2种定义方法:1是使用小括号定义,2是省略小括号
元组的拆分法
a,b,c=1,3,5
print(c,b,a)
#快读交换变量值
a,b=1,2
b,a = a,b
# 元组拆分,只要前2个值
values = 84,68,95,75,49,96
a,b,*rest=values #这里用*rest代替后面的所有变量,*是占位通配符
print(a,b,rest)
- 列表
list_v=[1,3,5,8]
列表是有序的,里面的元素可以是任何类型的。
列表是使用中括号定义的。
info_list=['jack',18,'Female',(95,85,121),{21,25,36}]
print(info_list[2])
print(info_list[0])
print(info_list[-2])
info_list=['jack',18,'Female',(95,85,121),{21,25,36}]
print(info_list[2])
print(info_list[0])
print(info_list[-2])
#切片(注意python的索引是从0开始,区间是左闭右开,不包括右边的区间的值)
print(info_list[1:3])#输出第1个到第2个。
print(info_list[1:-2])#输出第1个到倒数第3个
print(info_list[3:]) #输出第3个到最后一个
print(info_list[:-2])#输出从最开始到倒数第三个
print(info_list[::2])#从头到尾每2个取一个样
print(info_list[1:-1:2])#头尾各删除1个后,每2个取一个样
#列表元素的增加
print(info_list+[4]) #在列表最后增加一个元素4
print(info_list * 2 ) #列表复制自己,最终输出是2倍长的原始list
#注意这里的乘号不是乘法
- 字典
name_list={'zhangsan':12,'lisi':21,'zhaoliu':25}
字典是由大括号和键值对定义的。不同的键值对使用逗号分割。
每个键值对前面的是索引,后面的是值,索引:值
。
字典可以实现增删改查
name_list={
'zhangsan':22,
'lisi':21,
'zhaoliu':25
}
print(name_list)
name_list['wangwu']=26#字典里新增一个人王五,值是26.
print(name_list)
del name_list['lisi']#删除字典里李四
print(name_list)
name_list['zhangsan']=24#修改张三的值
print(name_list)
print("zhaoliu" in name_list) #查找赵六是否在字典中
print("zhaosi" in name_list) #查找赵四是否在字典中
判断语句
if只出现1次,elifke可出现0次到无数次,else可出现0次或1次。
注意每次条件后面都必须有:
英文的冒号。
a = 100
if a >10:
print(f"{a}:a 大于10")
s=96
if s <60:
print("不及格")
elif a > 90:
print("优秀")
else:
print("及格")
循环语句
- for循环
#列表for循环
list1 = ["zhao","liu","zhang","wang","li"]
for i in list1:
print(f"你的姓氏是:{i}")
#字典for循环
name_list={'zhangsan':12,'lisi':21,'zhaoliu':25}
for name in name_list.keys():#遍历键名
print(f"人员名单中有:{name}")
for age in name_list.values():#遍历键值
print(f"人员的年龄是:{age}")
for name,age in name_list.items():#同时遍历键名和键值
if age >= 18:
print(f"成年的学生有:",name,age)
else:
print(f"未成年的学生有:",name,age)
- while循环
a = 10
while a >0:
print(a)
a-=1
- continue和break语句
# continue 是用于中断本轮循环并进入下一轮循环,在for和while中均有效
a = 1
while a < 10:
a +=2
if a > 7:
continue
print(a)
# break 是完全中止循环,在for和while中均有效
a = 12
while a > 0:
a -=1
if a % 2 ==0:
print(a)
if a == 6:
break
列表推导式
value = []
for i in [1,2,3]:
value = value + [i**2]
print(value) #输出是[1, 4, 9]
value = [i**2 for i in [1,2,3]]
print(value) #输出是[1, 4, 9]
value = []
for i in list(range(1,5)):#生成1到5的自然数,然后遍历
if i < 4:
value = value + [i**2]
print(value) #输出是[1, 4, 9]
value = [ i**2 for i in range(1,5) if i<4 ] #输出是[1, 4, 9]
print(value)
高级变量之间的转换
集合、元组、列表、字典之间可以无缝切换
set、tuple、list、dict
# 定义变量
set_v = {1,2,3}
tuple_v = (1,2,3)
list_v = ["zhangsan","lisi","wangwu"]
dict_v = { 'a':1 , 'b':2 , 'c':3 }
#把字典的键名转为集合
print(set(dict_v.keys()))
#把字典的键值对转为元组
print(tuple(dict_v.items()))
#把字典的键值转为列表
print(list(dict_v.values()))
#注意把其他格式的转为字典的时候,需要使用zip函数,使2个容器内的元素配对
print(dict(zip(list_v,set_v)))
函数
#传统的传参,固定传输参数数量为2
def addstr(a,b):
"""
函数的功能是返回两个字符串的拼接结果
"""
return a+b
addstr("zhansan","mazi")
#不定参数数量,可以无限制传参
def menu(*args):
"""
可以传入任意数量的参数,(利用元组拆分)
"""
return args
menu("豆包","油条","菜包","花卷")
# 多个普通参数和最后一个是任意数量的参数
def person_info(name,age,*hobby):
"""
参数1是姓名,参数2是年龄,参数3可以是很多内容
"""
return name,age,hobby
person_info("zhangsan",12,"soccer","rap")
# 多个普通参数,最后一个是任意数量的键值对参数
def namelist(in1,in2,**kwargs):
'''
多个键值对的输入测试
'''
kwargs['zhangsan']=in1
kwargs['lisi']=in2
return kwargs
namelist(23,35)#只传入2个键值
namelist(23,35,maliu=28,zhaosi=31)#传入2个键值,后面跟上其他的键值对
#函数的关键字调用
def person_info(name,age,hobby):
"""
参数1是姓名,参数2是年龄,参数3爱好
"""
return name,age,hobby
person_info("zhangsan",12,"soccer")#这里按照函数的参数位置顺序传参
person_info(age=18,name="zhangsan",hobby="soccer") #这里是指定参数名传参
#函数指定参数的默认值(注意:有默认值的参数必须在最后面,但是可以有多个参数有默认值)
def person_info(name,age,hobby="table tennis"):
"""
参数1是姓名;参数2是年龄;参数3爱好,默认值是:乒乓球
"""
return name,age,hobby
person_info("zhangsan",12,"soccer")#这里传入了所有的参数
person_info("zhangsan",18)#这里第三个参数使用默认值
类class
class Counter: #定义一个类
"""一个加减计算器"""
def __init__(self,a,b):#特殊方法
'''a和b公共变量,也是self的属性'''
self.a = a
self.b = b
self.gender = 'man' #一个带有默认值的属性
def add(self):#自定义加法
'''加法'''
return self.a + self.b
def sub(self):#自定义减法
'''减法'''
return self.a - self.b
cnt = Counter(5,26) #创建一个实例cnt
print(cnt.a,cnt.b) #访问类的属性
print(cnt.add()) #调用在类的方法
print(cnt.gender) #输出默认的性别
cnt.gender = "female" #修改创建的实例cnt的默认的gender属性值
类的继承和掠夺
#定义1个类
class Counter: #定义一个类
"""一个加减计算器"""
def __init__(self,a,b):#特殊方法
'''a和b公共变量,也是self的属性'''
self.a = a
self.b = b
self.gender = 'man' #一个带有默认值的属性
def add(self):#自定义加法
'''加法'''
return self.a + self.b
def sub(self):#自定义减法
'''减法'''
return self.a - self.b
#定义一个继承上面的类的类
class Calcu(Counter):
'''一个可以加减乘除的计算器'''
def __init__(self,a,b):
'''引用父类的属性'''
super().__init__(a,b) #继承父类的属性
def mul(self):
'''乘法'''
return self.a * self.b
def div(self):
'''除法'''
if self.b != 0:
return self.a / self.b
else:
raise ValueError("除数不能为 0")
mxx = Calcu(2,8) #实例化Calcu
mxx.add() #调用继承的方法
mxx.gender #查看基础的属性值
mxx.div() #调用该类自己定义的方法
#定义一个掠夺的类
class Amrc:
'''一个本身只能幂次方的计算器,掠夺上面的加减乘除的功能的类Calcu'''
def __init__(self,i,j):
'''公共变量'''
self.i = i
self.j = j
self.mxx = Calcu(i,j) #这里掠夺了Calcu的类的方法
def powe(self):
'''幂次方运算,前面是底数,后面是指数'''
return self.i ** self.j
testAmrc = Amrc(2,5) #创建一个Amrc实例
testAmrc.powe() #使用自己定义的方法,幂次方
testAmrc.mxx.mul() # 掠夺来的方法,乘法
numpy包(数组库)
整(数)型和浮点型之间的变换
import numpy as np
arr1 = np.array([1,5,7]) #创建整数型数组
print(arr1)
arr2 = np.array([1,5.364,7.621]) #创建浮点型数组,只要有1个是浮点型,则整个数组都是浮点型
print(arr2)
#往浮点数组里添加整型数,会自动把添加的整型数转为浮点型。
arr1[-1]= 13.1524
print(arr1) #输出是[ 1 5 13]
#往整型数组里添加浮点型数,会自动截断要添加的浮点数的小数部分
arr2[0] = 101
print(arr2) #输出是[101. 5.364 7.621]
#改变整个数组为整数型
arr2 = arr2.astype(int)
print(arr2) #[101 5 7]
#改变整个数组为浮点型
arr1 = arr1.astype(float)
print(arr1) #[ 1. 5. 13.]
#整数型的数组在运算过程中很容易变为浮点型数组,浮点型一般不会变为整型数
#整型数(加、减、乘) 浮点数都会自动变为浮点型运算,除法任何时候都会变为浮点型运算
print(arr2+1.0) #输出[102. 6. 8.]
print(arr2 * 1.0) #输出[101. 5. 7.]
print(arr2 / 1) # [101. 5. 7.]
数组维度的转换
一维数组一般称为向量,二维数组一般成为矩阵。
import numpy as np
# 每个中括号就是一个维度,无论维度有多少个,最后一个是列数,倒数第2个是行数。
arr1 = np.ones((3)) #一个维度的数组,即3列
print(arr1)
arr1 = np.ones((2,3)) #2个维度的数组,即2行3列
print(arr1)
arr3 = np.ones((1,3,7)) #创建值都是1的数组,3个维度的数组,前面还有1个维度,3行7列。
print(arr3)
print(arr3.shape) #shape显示各个维度的数量(形状)
arr4 = np.arange(10) #一维数组,[0 1 2 3 4 5 6 7 8 9]
print(arr4)
arr5=arr4.reshape((5,2)) #上面是10个数,所以这里转为2维度时候,2个维度的数量的乘积必须是10.
print(arr5)
arr6=arr5.reshape((10)) #把上面的2维度再转回为1个维度
print(arr6)
数组的创建
import numpy as np
arr1 = np.array([1,3,5]) #创建1维向量
print(arr1)
arr2 = np.array([[1,3,5],[2,4,7]]) #创建2维数组,矩阵
print(arr2)
arr3 = np.array([[1,3,5]]) #创建2维数组,行矩阵
print(arr3)
arr4 = np.array([[1],[3],[5]]) #创建2维数组,列矩阵
print(arr4)
arr2 = np.arange(10,20) #[10 11 12 13 14 15 16 17 18 19]
print(arr2)
arr3 = np.arange(10,20,2) #[10 12 14 16 18]
print(arr3)
#生成0矩阵和1矩阵
arr1= np.zeros(3)#1维度的3个0的向量
print(arr1)
arr2= np.ones((1,3))#2维度的1行3列的1矩阵
print(arr2)
arr3= 3.14 * np.ones((2,3)) #先生成2行3列的1矩阵,然后再和前面的数字相乘,所有值就都变成了3.14
print(arr3)
#创建随机数组
np.random.random(5) #生成0-1之间的随机浮点数
np.random.randint(1,100,(2,3)) #生成1到100之间的2行3列的随机数
np.random.randn(5) #生成均值是0,标准差是1的5个随机浮点数
np.random.normal(29,5,(2,3)) #生成均值是29,标准差是5的2行3列的随机浮点数
数组的索引和切片
注意numpy切片是引用,只是引用原来数组的位置,如果原数组变了,则切片的引用也会自动变化,即使是先切片后修改原数组,切片的值也会自动变化
import numpy as np
#规则一样:下标从0开始,区间都是左闭右开
arr1 = np.arange(1,10)
print(arr1)
print(arr1[3]) #第3个值
print(arr1[-1]) #倒数第1个值
arr1[3]=3.011##注意上面是直接修改第3个值,但是原始的是整型矩阵,所以相当于在整型里添加一个浮点型,会自动舍去小数
print(arr1) #[1 2 3 3 5 6 7 8 9]
arr2 = np.array([[1,2,3],[4,5,6]])
print(arr2)
print(arr2[1,2]) #第1个维度,第2个值 6. 注意:维度和值的最开始的索引都是0
arr3 = np.arange(1,25).reshape(4,6)
print(arr3)
print(arr3[[2,3],[3,1]]) #[16,20]
arr3[[2,3],[3,1]]=55 #修改上面的两个值所在位置的值为55
print(arr3)
##切片和python的切片一样
arr1[1:] #从第1个到最后
arr1[:2] #从最开始第0个到第2个,注意不包含第2个,右侧的区间是开区间
arr1[::2] #从头到尾每2个取1个
arr1[1:-1:2] #掐头去尾,每2个取1个
arr3[2,:] #提取矩阵第2行
arr3[0:2,:] #提取矩阵第0行和第1行,注意不包括第2行,右侧区间是开区间
arr3[:,3] #提取矩阵第3列
arr3[:,-3:-1] #提取矩阵倒数第3列到倒数第2列,不包含倒数第1列
注意numpy切片是引用,如果需要保存切片的值不变,则必须使用.copy()
备份
arr1 = np.arange(1,19).reshape(3,6)
print(arr1)
copy_arr = arr1[0,1:2].copy()#备份切片为新的变量
print(copy_arr)#[2]
arr1[0,1:2]= 101#修改该位置的值为101
print(copy_arr)#[2]
print(arr1[0,1:2])#[101]
矩阵的变换操作
#矩阵的转置
arr1 = np.arange(1,9) #创建1维向量
print(arr1)
arr2 = arr1.reshape((1,-1)) #转为矩阵
print(arr2)
arr3 = arr2.T #转置矩阵,必须是矩阵才能转置,向量不能被转置
print(arr3)
#数组反转
arr4 = np.flipud(arr1)#反转向量
print(arr4)
arr5 = np.flipud(arr3)#上下反转矩阵
print(arr5)
arr6 = np.fliplr(arr2)#左右反转矩阵
print(arr6)
arr7 = arr1.reshape(2,4) #向量转为2行4列的矩阵
print(arr7)
arr8 = arr7.reshape(4,2) #矩阵转为4行2列的矩阵
print(arr8)
#数组的拼接
arr1 = np.array( [1,2,3] )
arr2 = np.random.randn(3)
arr3 = np.concatenate([arr1,arr2]) #常规的cat
print(arr3)
arr4 = arr3.reshape(2,3)
arr5 = np.arange(10,16).reshape(2,3)
arr6 = np.concatenate([arr4,arr5],axis=1) #列后面追加列
arr7 = np.concatenate([arr4,arr5],axis=0) #常规的cat,行后面追加
print(arr5)
print(arr6)
print(arr7)
数组的分裂
arr = np.arange(0,100,10)
arr1,arr2,arr3=np.split(arr,[2,8]) #从第2个和第8个分割,即arr1有元素0,1 arr2有元素2,3,4,5,6,7,; arr3有元素8,9
print(arr1,arr2,arr3)
arr4 = arr.reshape(2,5)
print(arr4)
arr1,arr2 = np.split(arr4,[1],axis=0) #默认是分割行
#print(arr1,arr2)
arr1,arr2 = np.split(arr4,[1],axis=1) #此处是分割列
#print(arr1,'\n\n',arr2)
arr1,arr2,arr3 = np.split(arr4,[1,3],axis=1) #此处是分割列,arr1是第0列,arr2是第1到第2列,arr3是第3列到最后1列
print(arr1,'\n\n',arr2,'\n\n',arr3)
数组的运算
- 加减乘除
+-*/
-
**
幂次方 2**4 16 ()
-
//
整除取商 16 // 3 5 -
%
整除取余数 16%3 1
import numpy as np
arr1 = np.arange(-1,-9,-1).reshape(2,4)
arr2 = -arr1
print(arr1)
print(arr2)
arr1 + arr2 #矩阵加法
arr1 - arr2 #矩阵减法
arr1 * arr2 #矩阵中对应位置元素各自相乘
arr1 / arr2 #矩阵除法
arr1 ** arr2 #矩阵的幂次方,
#广播
#向量和矩阵之间运算,向量会自动升级为行矩阵
#某个行或列矩阵和另一个矩阵运算,则自动适配另一个矩阵的形状
arr1 = np.array([-100,0,100])
print(arr1)
arr2 = np.random.random((10,3))
print(arr2)
print(arr1 * arr2) #arr1就被广播为和arr2相同的行数,然后再相乘
image.png
数组的函数
np.dot实现的乘积
arr1 = np.arange(1,5)
arr2 = np.arange(1,5)
print(arr1)
np.dot(arr1,arr2) #等于前面的向量的每个元素分别相乘然后相加。30=1*1+2*2+3*3+4*4
arr3 = np.arange(20).reshape(4,5) #生成4*4的矩阵
print(arr3) #
# np.dot是矩阵的乘法, 等于是[1*0+2*5+3*10+4*15,,,1*4+2*9+3*14+4*19] 即[100, 110, 120, 130, 140]
np.dot(arr1,arr3) #arr1是(1,4),arr3是(4,5),所以输出的维度是(1,5)
arr4 = np.arange(8).reshape(2,4) #生成2*4的矩阵
print(arr4)
print(np.dot(arr4,arr3),arr4.shape,arr3.shape)
# arr4 shape是(2,4) arr3 是(4,5),所以输出是(2,5)
#前面的第2个维度必须和后面的第1个维度的值一样,否则无法使用np.dot
数学函数
arr1 = np.array([-10,20,51,102])
np.abs(arr1) #求绝对值
np.pi #π值
theta = np.arange(3)*np.pi
np.sin(theta) #正弦sin值
np.cos(theta) #余弦cos值
np.tan(theta) #正切值tan
np.exp(theta) #e的对应数次幂
#np.log(arr1) #ln(x)
#np.log2(arr1)/np.log(2) #log2(X)
#聚合函数
arr1 = np.random.random(10).reshape(5,2)
print(arr1)
print(np.max(arr1,axis=0)) #每列的最大值
print(np.max(arr1,axis=1)) #每行的最大值
print(np.max(arr1)) #整个矩阵的最大值
print(np.sum(arr1,axis=0)) #按列的求和
print(np.sum(arr1,axis=1)) #按行的求和
print(np.sum(arr1)) #整个矩阵求和
#大型矩阵有缺失值,所以提供了忽略缺失值的函数
np.nansum() #求和
np.nanprod() #求导
np.nanmean() #求均值
np.nanstd() #求标准差
np.nanmax() #求最大值
np.nanmin() #求最小值
布尔型数组
arr1 = np.arange(1,9).reshape(4,2)
print(arr1)
print(arr1>=5)
arr2 =np.fliplr(arr1)
print(arr1>arr2)
print("\n",(arr1>5) & (arr1<8)) #与
print("\n",(arr1>5) | (arr1<8)) #或
print("\n",~(arr1>5)) #非
arr3 = np.random.randint(-100,100,25)
np.sum(np.abs(arr3)<50) #计算矩阵中绝对值小于50的数量,这里是统计True的数量
np.any(arr1==arr2) #只要有一个是True就返回True
np.all(np.abs(arr3)>0) #判断是否所有的都为True,则返回True,否则就是False
np.where(arr3==np.max(arr3)) #找出数组中最大值所在的位置
np.where(arr3>np.mean(arr3)) #找出大于数组均值的值所在的位置
numpy和pytorch的对比
数组和张量之间可以互相转换
数组转张量ts=torch.tensor(arr)
张量转数组arr=np.array(ts)
image.png