TensorFlow使用Python自定义op和损失函数
TensorFlow使用Python自定义op和损失函数
TensorFlow是静态图结构,即必须把所有的操作以及网络结构定义好(后来有了动态图功能,即Eager Execution ),在没有用tf.Session().run接口填充值之前是没有实际值的。因此,在网络搭建的时候,是不能对tensor进行判值操作的,即不能插入if...else...之类的代码。这相较于numpy array,Tensorflow中对tensor的操作接口灵活性并没有那么高,为了扩展Tensorflow程序的灵活性,Tensorflow提供了tf.py_func接口。
如果使用tf.py_func调用了非TensorFlow原生的接口,使用第三方库定义某个功能时,很容易出现如下错误:
ValueError: No gradients provided for any variable, check your graph for ops that do not support gradients, between variables ["<tf.Variable 'W:0' shape=(1,) dtype=float32_ref>", "<tf.Variable 'b:0' shape=(1,) dtype=float32_ref>"] and loss Tensor("Mean:0", shape=(), dtype=float32).
出现这个原因,本质上来说,就是我们利用第三方库自定义层,相关变量没有计算梯度!我们知道网络需要训练,每一层都需要定义计算前向和反向转播的,若采用TensorFlow自带的OP,是没有问题,因为Google以及实现前向和反向的过程。而采用第三方库时,只是实现了前向转播,而反向转播计算过程,我们是没有定义,所以就出现No gradients provided for any variable的错误!
如果你想想TensorFlow提供API一样,实现前向和反向转播的计算,可以参考两种方法:
(1)C++层自定义OP:基本流程:注册op,实现op,创建python接口,实现op梯度计算(如果不需要求导也可以直接pass掉,实现可以在python端也可以用py_func去包装其他python函数,也可以再写一个C++ op来专门计算梯度),测试等。这部分可以参考:
https://blog.csdn.net/u012436149/article/details/73737299
https://www.zhihu.com/question/67352230
https://zhuanlan.zhihu.com/p/34169502
(2)Python层自定义OP:这个方法需要使用tf.py_func()调用第三方库实现前向计算过程,使用tf.RegisterGradient注册梯度反向传播函数实现反向转播计算过程。该方法是我比较推荐的,相比第一种方法,简单很多了,对于C++不是很熟悉的小朋友来说,在Python上自定义OP再好不过了!
目录
TensorFlow自定义op和Python损失函数
1.线性回归
1.1均方误差tf.reduce_mean(tf.square())
1.2 自定义均方误差
2. 出现No gradients provided for any variable的原因分析
3. 自定义损失函数
3.1@tf.RegisterGradient修饰器
3.2 gradient_override_map
3.3 自定义梯度反向传播函数
3.4 完整代码:
4. 使用tf.RegisterGradient函数
4.1 tf.RegisterGradient()函数
4.2 完整的代码:
1.线性回归
先看一个线性回归的列子:https://www.cnblogs.com/selenaf/p/9102398.html
对于直线y=Wx+b,随机生成一些加入噪声的数据点,如下图所示。我们可以让TensorFlow建立线性回归模型,通过拟合这些数据去学习W和b的值。
1.1均方误差tf.reduce_mean(tf.square())
损失函数可以选择均方误差,可以直接调用TensorFlow的tf.reduce_mean(tf.square())实现均方差损失,这样完整的训练代码可如下实现:
#! /usr/bin/env python
# coding=utf-8import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
print(tf.__version__)
def gen_data(w,b,num_points):'''y=wx+b:param w::param b::param num_points::return:'''vectors_set=[]x_data=[]y_data=[]for i in range(num_points):x1=np.random.normal(0.0,0.55) #横坐标,进行随机高斯处理化,以0为均值,以0.55为标准差y1=x1*w+b+np.random.normal(0.0,0.03) #纵坐标,数据点在y1=x1*0.1+0.3上小范围浮动vectors_set.append([x1,y1])x_data=[v[0] for v in vectors_set]y_data=[v[1] for v in vectors_set]plt.scatter(x_data,y_data,c='r')plt.show()x_data=np.array(x_data,dtype=np.float32)y_data=np.array(y_data,dtype=np.float32)return x_data,y_datadef train_linear_regression(x_data,y_data,max_iterate):''':param x_data::param y_data::param max_iterate: 最大迭代次数:return:'''print("x_data.shape:{}".format(x_data.shape))print("y_data.shape:{}:".format(y_data.shape))# 定义线性回归模型W = tf.Variable(tf.random_uniform([1], -1.0, 1.0), name='W') # 生成1维的W矩阵,取值是[-1,1]之间的随机数b = tf.Variable(tf.zeros([1]), name='b') # 生成1维的b矩阵,初始值是0y = W * x_data + b # 经过计算得出预估值y# 定义计算图graph = tf.get_default_graph()# 定义均方误差loss = tf.reduce_mean(tf.square(y - y_data), name='loss') # 以预估值y和实际值y_data之间的均方误差作为损失# 定义优化器optimizer = tf.train.GradientDescentOptimizer(0.1) # 采用梯度下降法来优化参数 学习率为0.5train = optimizer.minimize(loss, name='train') # 训练的过程就是最小化这个误差值# 训练with tf.Session(graph=graph) as sess:init = tf.global_variables_initializer()sess.run(init)for step in range(max_iterate): # 执行20次训练_,pre_W,pre_b,pre_loss=sess.run([train,W,b,loss])print("step:{},W={},b={},loss={}".format(step+1,pre_W,pre_b,pre_loss))if __name__=='__main__':w=0.1b=0.3num_points=1000max_iterate=1000x_data, y_data=gen_data(w, b, num_points)train_linear_regression(x_data, y_data, max_iterate)
step:1,W=[0.33111742],b=[0.05976159],loss=0.10794320702552795
step:2,W=[0.31746817],b=[0.10756931],loss=0.07375720143318176
step:3,W=[0.3046297],b=[0.14581403],loss=0.05137966573238373
step:4,W=[0.29255316],b=[0.17640844],loss=0.03661665320396423
step:5,W=[0.28119272],b=[0.20088267],loss=0.02677750028669834
step:6,W=[0.2705055],b=[0.22046085],loss=0.020134398713707924
step:7,W=[0.2604512],b=[0.23612225],loss=0.015576418489217758
step:8,W=[0.25099206],b=[0.2486503],loss=0.01238801795989275
step:9,W=[0.24209262],b=[0.25867173],loss=0.010107231326401234
......
......
step:995,W=[0.10031797],b=[0.29867724],loss=0.0008959544938988984
step:996,W=[0.10031797],b=[0.29867724],loss=0.0008959544938988984
step:997,W=[0.10031797],b=[0.29867724],loss=0.0008959544938988984
step:998,W=[0.10031797],b=[0.29867724],loss=0.0008959544938988984
step:999,W=[0.10031797],b=[0.29867724],loss=0.0008959544938988984
step:1000,W=[0.10031797],b=[0.29867724],loss=0.0008959544938988984
通过迭代1000次,模型可以很好的拟合数据,并且学习到权值W=[0.10031797],b=[0.29867724],这与设定w=0.1 b=0.3的差异很小了
1.2 自定义均方误差
上面的训练代码,损失函数是直接调用TensorFlow的tf.reduce_mean(tf.square())实现均方差损失,现在问题来呢?我们可否不调用TensorFlow的 API接口,自己使用第三方的Python库自定义TensorFlow的损失函数,于是,我们尝试使用Python math库定义一个平方差square_loss:
def square_loss(array1,array2):'''使用math自定义平方损失函数:Square loss=(x-y)^2:param array1: input x:param array2: input y:return:'''# loss=np.square(array1-array2)square=[]for a1,a2 in zip(array1,array2):s=math.pow(a1-a2,2)square.append(s)loss=np.array(square,dtype=np.float32)return loss
说明:这里square_loss是使用math的Python包实现平方差,实质上一种更简单的方法,是使用Numpy执行loss=np.square(array1-array2)即可,这两种方式是等价,之所以没有用Numpy,那是因为TensorFlow的tensor变量很多都支持Nump的计算,很难体现出博客的用意:使用第三方的Python库自定义TensorFlow的损失函数。当然,实际开发,还是建议使用Numpy实现各种复杂的计算。
由于使用第三方的Python库实现的函数,这需要借助TF的tf.py_func中传入自定义的loss函数
tf.py_func的用法:请参考:https://www.tensorflow.org/api_docs/python/tf/py_func
tf.py_func( func,inp,Tout,stateful=True,name=None)前三个参数说明:
第一个参数func,也是最重要的,是一个用户自定制的函数,输入numpy array,输出也是numpy array,在该函数中,可以自由使用np.操作。
第二个参数inp,是func函数接收的输入,是一个列表。
第三个参数Tout,指定了func函数返回的numpy array转化成tensor后的格式,如果是返回多个值,就是一个列表或元组;如果只有一个返回值,就是一个单独的dtype类型(当然也可以用列表括起来)。
于是,我把训练的代码的loss定义如下:
# 定义均方误差# loss = tf.reduce_mean(tf.square(y - y_data), name='loss') # 以预估值y和实际值y_data之间的均方误差作为损失# loss = tf.reduce_mean(square_loss(y,y_data))loss = tf.reduce_mean(tf.py_func(square_loss, inp=[y, y_data], Tout=tf.float32))
好了,定义完成,Run,终于出现了我想要说的错误:
ValueError: No gradients provided for any variable, check your graph for ops that do not support gradients, between variables ["<tf.Variable 'W:0' shape=(1,) dtype=float32_ref>", "<tf.Variable 'b:0' shape=(1,) dtype=float32_ref>"] and loss Tensor("Mean:0", shape=(), dtype=float32).
2. 出现No gradients provided for any variable的原因分析
出现这个原因,本质上来说,就是我们利用第三方库自定义的损失或者其他层,相关变量没有计算梯度!我们知道网络需要训练,每一层都需要定义和计算前向和反向转播的,若采用TensorFlow自带的OP,是没有问题,因为Google以及实现前向和反向的过程。而采用第三方库时,只是实现了前向转播,而反向转播计算过程,我们是没有定义,所以就出现No gradients provided for any variable的错误了!
3. 自定义损失函数
在自定义损失函数前,先介绍两个TensorFlow的函数tf.RegisterGradient和 tf.Graph.gradient_override_map
3.1@tf.RegisterGradient修饰器
@tf.RegisterGradient修饰符在定义一个新的 op 类型时使用。对于具有 m 个输入和 n 个输出的运算,梯度函数是一个采用原始的 Operation 和 n Tensor 对象(表示与 op 的每个输出相关的梯度),并返回 m Tensor 对象(表示相对于 op 的每个输入的部分梯度)的函数。
例如,假设该类型的"Sub"操作需要两个输入 x 和 y,并返回一个单一的输出 x - y,则以下梯度函数将被注册:
@tf.RegisterGradient("Sub")
def _sub_grad(unused_op, grad):return grad, tf.negative(grad)
修饰符参数 op_type 是操作的字符串类型。这对应于定义操作的原始 OpDef. name 字段。
参考:https://tensorflow.google.cn/api_docs/python/tf/RegisterGradient
3.2 gradient_override_map
tf.Graph.gradient_override_map(op_type_map):返回一个覆盖梯度函数的上下文管理器,此管理器用于覆盖ops的梯度函数。通过这个管理器,我们可以针对自定义operation,使用自己的gradient函数。例如
# 先注册一个gradient函数
@tf.RegisterGradient("CustomSquare")
def _custom_square_grad(op, grad):# ...with tf.Graph().as_default() as g:c = tf.constant(5.0)s_1 = tf.square(c) # 使用tf.square默认的gradientwith g.gradient_override_map({"Sqaure": "CustomSquare"}):s_2 = tf.square(s_2): # 使用自定义的_custom_square_grad函数来计算s_2的梯度
3.3 自定义梯度反向传播函数
使用TensorFlow的修饰器@tf.RegisterGradient("LossGradient"),定义一个平方差损失square_loss_grad函数的梯度计算过程:
平方差损失:
对x求偏导:
对 y求偏导:
对应的Python代码如下:
@tf.RegisterGradient("LossGradient")
def square_loss_grad(op, grad):'''使用修饰器,建立梯度反向传播函数。其中op.input包含输入值、输出值,grad包含上层传来的梯度:param op::param grad::return:'''x = op.inputs[0]y = op.inputs[1]# 计算平方损失的梯度:loss=(x-y)^2grad_x = 2 * grad * (x - y) # 对x求导:grad_x=2(x-y)grad_y = tf.negative(2 * grad * (x - y)) # 对y求导:grad_y=-2(x-y)return grad_x, grad_y
然后在调用square_loss时插入tf.get_default_graph().gradient_override_map({"PyFunc": 'LossGradient'})
def my_loss(y, y_data):with tf.get_default_graph().gradient_override_map({"PyFunc": 'LossGradient'}):loss=tf.py_func(square_loss, inp=[y, y_data], Tout=tf.float32)return loss
最后训练代码的loss修改如下:
# 定义均方误差# loss = tf.reduce_mean(tf.square(y - y_data), name='loss') # 以预估值y和实际值y_data之间的均方误差作为损失# loss = tf.reduce_mean(square_loss(y,y_data))# loss = tf.reduce_mean(tf.py_func(square_loss, inp=[y, y_data], Tout=tf.float32))loss=tf.reduce_mean(my_loss(y,y_data))
3.4 完整代码:
#! /usr/bin/env python
# coding=utf-8import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import mathprint(tf.__version__)
def gen_data(w,b,num_points):'''y=wx+b:param w::param b::param num_points::return:'''vectors_set=[]x_data=[]y_data=[]for i in range(num_points):x1=np.random.normal(0.0,0.55) #横坐标,进行随机高斯处理化,以0为均值,以0.55为标准差y1=x1*w+b+np.random.normal(0.0,0.03) #纵坐标,数据点在y1=x1*0.1+0.3上小范围浮动vectors_set.append([x1,y1])x_data=[v[0] for v in vectors_set]y_data=[v[1] for v in vectors_set]plt.scatter(x_data,y_data,c='r')plt.show()x_data=np.array(x_data,dtype=np.float32)y_data=np.array(y_data,dtype=np.float32)return x_data,y_datadef square_loss(array1,array2):'''使用math自定义平方损失函数:Square loss=(x-y)^2:param array1: input x:param array2: input y:return:'''# loss=np.square(array1-array2)square=[]for a1,a2 in zip(array1,array2):s=math.pow(a1-a2,2)square.append(s)loss=np.array(square,dtype=np.float32)return loss@tf.RegisterGradient("LossGradient")
def square_loss_grad(op, grad):'''使用修饰器,建立梯度反向传播函数。其中op.input包含输入值、输出值,grad包含上层传来的梯度:param op::param grad::return:'''x = op.inputs[0]y = op.inputs[1]# 计算平方损失的梯度:loss=(x-y)^2grad_x = 2 * grad * (x - y) # 对x求导:grad_x=2(x-y)grad_y = tf.negative(2 * grad * (x - y)) # 对y求导:grad_y=-2(x-y)return grad_x, grad_ydef my_loss(y, y_data):with tf.get_default_graph().gradient_override_map({"PyFunc": 'LossGradient'}):loss=tf.py_func(square_loss, inp=[y, y_data], Tout=tf.float32)return lossdef train_linear_regression(x_data,y_data,max_iterate):''':param x_data::param y_data::param max_iterate: 最大迭代次数:return:'''print("x_data.shape:{}".format(x_data.shape))print("y_data.shape:{}:".format(y_data.shape))# 定义线性回归模型W = tf.Variable(tf.random_uniform([1], -1.0, 1.0), name='W') # 生成1维的W矩阵,取值是[-1,1]之间的随机数b = tf.Variable(tf.zeros([1]), name='b') # 生成1维的b矩阵,初始值是0y = W * x_data + b # 经过计算得出预估值y# 定义计算图graph = tf.get_default_graph()# 定义均方误差# loss = tf.reduce_mean(tf.square(y - y_data), name='loss') # 以预估值y和实际值y_data之间的均方误差作为损失# loss = tf.reduce_mean(square_loss(y,y_data))# loss = tf.reduce_mean(tf.py_func(square_loss, inp=[y, y_data], Tout=tf.float32))loss=tf.reduce_mean(my_loss(y,y_data))# 定义优化器optimizer = tf.train.GradientDescentOptimizer(0.1) # 采用梯度下降法来优化参数 学习率为0.5train = optimizer.minimize(loss, name='train') # 训练的过程就是最小化这个误差值# 训练with tf.Session(graph=graph) as sess:init = tf.global_variables_initializer()sess.run(init)for step in range(max_iterate): # 执行20次训练_,pre_W,pre_b,pre_loss=sess.run([train,W,b,loss])print("step:{},W={},b={},loss={}".format(step+1,pre_W,pre_b,pre_loss))if __name__=='__main__':w=0.1b=0.3num_points=1000max_iterate=1000x_data, y_data=gen_data(w, b, num_points)train_linear_regression(x_data, y_data, max_iterate)
4. 使用tf.RegisterGradient函数
4.1 tf.RegisterGradient()函数
当然也可以不使用装饰器,TensorFlow提供了tf.RegisterGradient()函数,可以直接调用梯度函数
def py_func_grad(func, inp, Tout, stateful=True, name=None, grad=None):'''Custom py_func with gradient support:param func: 前向传播函数:param inp: func函数的输入参数:param Tout: func函数的输出参数:param stateful: :param name: :param grad: 反向转播函数:return: '''# Need to generate a unique name to avoid duplicates:rnd_name = 'PyFuncGrad' + str(np.random.randint(0, 1E+8))tf.RegisterGradient(rnd_name)(grad)g = tf.get_default_graph()with g.gradient_override_map({"PyFunc": rnd_name,"PyFuncStateless": rnd_name}):return tf.py_func(func, inp, Tout, stateful=stateful, name=name)
最后训练代码的loss修改如下:
# 定义均方误差# loss = tf.reduce_mean(tf.square(y - y_data), name='loss') # 以预估值y和实际值y_data之间的均方误差作为损失# loss = tf.reduce_mean(square_loss(y,y_data))# loss = tf.reduce_mean(tf.py_func(square_loss, inp=[y, y_data], Tout=tf.float32))# loss=tf.reduce_mean(my_loss(y,y_data))loss=tf.reduce_mean(py_func_grad(square_loss, inp=[y,y_data], Tout=tf.float32, grad=square_loss_grad))
4.2 完整的代码:
#! /usr/bin/env python
# coding=utf-8import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
import mathprint(tf.__version__)
def gen_data(w,b,num_points):'''y=wx+b:param w::param b::param num_points::return:'''vectors_set=[]x_data=[]y_data=[]for i in range(num_points):x1=np.random.normal(0.0,0.55) #横坐标,进行随机高斯处理化,以0为均值,以0.55为标准差y1=x1*w+b+np.random.normal(0.0,0.03) #纵坐标,数据点在y1=x1*0.1+0.3上小范围浮动vectors_set.append([x1,y1])x_data=[v[0] for v in vectors_set]y_data=[v[1] for v in vectors_set]plt.scatter(x_data,y_data,c='r')plt.show()x_data=np.array(x_data,dtype=np.float32)y_data=np.array(y_data,dtype=np.float32)return x_data,y_datadef square_loss(array1,array2):'''使用math自定义平方损失函数:Square loss=(x-y)^2:param array1: input x:param array2: input y:return:'''# loss=np.square(array1-array2)square=[]for a1,a2 in zip(array1,array2):s=math.pow(a1-a2,2)square.append(s)loss=np.array(square,dtype=np.float32)return lossdef square_loss_grad(op, grad):'''使用修饰器,建立梯度反向传播函数。其中op.input包含输入值、输出值,grad包含上层传来的梯度:param op::param grad::return:'''x = op.inputs[0]y = op.inputs[1]# 计算平方损失的梯度:loss=(x-y)^2grad_x = 2 * grad * (x - y) # 对x求导:grad_x=2(x-y)grad_y = tf.negative(2 * grad * (x - y)) # 对y求导:grad_y=-2(x-y)return grad_x, grad_ydef py_func_grad(func, inp, Tout, stateful=True, name=None, grad=None):'''Custom py_func with gradient support:param func: 前向传播函数:param inp: func函数的输入参数:param Tout: func函数的输出参数:param stateful::param name::param grad: 反向转播函数:return:'''# Need to generate a unique name to avoid duplicates:rnd_name = 'PyFuncGrad' + str(np.random.randint(0, 1E+8))tf.RegisterGradient(rnd_name)(grad)g = tf.get_default_graph()with g.gradient_override_map({"PyFunc": rnd_name,"PyFuncStateless": rnd_name}):return tf.py_func(func, inp, Tout, stateful=stateful, name=name)def train_linear_regression(x_data,y_data,max_iterate):''':param x_data::param y_data::param max_iterate: 最大迭代次数:return:'''print("x_data.shape:{}".format(x_data.shape))print("y_data.shape:{}:".format(y_data.shape))# 定义线性回归模型W = tf.Variable(tf.random_uniform([1], -1.0, 1.0), name='W') # 生成1维的W矩阵,取值是[-1,1]之间的随机数b = tf.Variable(tf.zeros([1]), name='b') # 生成1维的b矩阵,初始值是0y = W * x_data + b # 经过计算得出预估值y# 定义计算图graph = tf.get_default_graph()# 定义均方误差# loss = tf.reduce_mean(tf.square(y - y_data), name='loss') # 以预估值y和实际值y_data之间的均方误差作为损失# loss = tf.reduce_mean(square_loss(y,y_data))# loss = tf.reduce_mean(tf.py_func(square_loss, inp=[y, y_data], Tout=tf.float32))# loss=tf.reduce_mean(my_loss(y,y_data))loss=tf.reduce_mean(py_func_grad(square_loss, inp=[y,y_data], Tout=tf.float32, grad=square_loss_grad))# 定义优化器optimizer = tf.train.GradientDescentOptimizer(0.1) # 采用梯度下降法来优化参数 学习率为0.5train = optimizer.minimize(loss, name='train') # 训练的过程就是最小化这个误差值# 训练with tf.Session(graph=graph) as sess:init = tf.global_variables_initializer()sess.run(init)for step in range(max_iterate): # 执行20次训练_,pre_W,pre_b,pre_loss=sess.run([train,W,b,loss])print("step:{},W={},b={},loss={}".format(step+1,pre_W,pre_b,pre_loss))if __name__=='__main__':w=0.1b=0.3num_points=1000max_iterate=1000x_data, y_data=gen_data(w, b, num_points)train_linear_regression(x_data, y_data, max_iterate)
TensorFlow使用Python自定义op和损失函数相关推荐
- tensorflow:自定义op
比官网介绍的更好理解,特此转载 tensorflow:自定义op简单介绍 2017年06月26日 13:32:55 阅读数:6094 tensorflow 自定义 op 本文只是简单的翻译了 http ...
- tensorflow自定义op:梯度
暂时并未解决我的问题,但感觉将来会有用,特此转载 . 在使用 tensorflow 的时候,有时不可避免的会需要自定义 op,官方文档对于 定义 op 的前向过程介绍挺详细,但是对于 梯度 的介绍有点 ...
- tensorflow:自定义op简单介绍
本文只是简单的翻译了 https://www.tensorflow.org/extend/adding_an_op 的简单部分,高级部分请移步官网. 可能需要新定义 c++ operation 的几种 ...
- Pytorch1.1.0 入门 自定义op(python)
因为需求,需要调研tensorRT与ONNX关于自定义层的方法.经过之前的调研,首先,关于onnx,开发者手册中的介绍有限,在已知的demo中没有关于onnx自定义层的,详情见TensorRT 5.1 ...
- TensorFlow实现自定义Op
『写在前面』 以CTC Beam search decoder为例,简单整理一下TensorFlow实现自定义Op的操作流程. 基本的流程 1. 定义Op接口 #include "tenso ...
- Python 扩展 Op
Python 扩展 Op 注意 :本文涉及的 Python Kernel 仅在 gcc 4.8.5 编译环境下充分测试,进一步的完善计划见 Issue 3951. 背景介绍 OneFlow 将各种对于 ...
- TensorFlow常用Python扩展包
TensorFlow常用Python扩展包 TensorFlow 能够实现大部分神经网络的功能.但是,这还是不够的.对于预处理任务.序列化甚至绘图任务,还需要更多的 Python 包. 下面列出了一些 ...
- python自定义包或模块在Linux服务器导入错误的解决办法
python自定义包或模块在Linux服务器导入错误的解决办法 在本地机器上跑python代码,自己定义的文件进行导包运行是没有问题,但是放到linux服务器上的时候就会提示 ImportError: ...
- python教程哪个版本好-tensorflow用python哪个版本更好?
tensorflow用python哪个版本? 一.安装anaconda tensorflow是基于python脚本语言的,因此需要安装python, 当然还需要安装numpy.scipy.six.ma ...
最新文章
- 死在“风口上的猪”人工智能初创企业倒闭的原因分析
- Spring MVC实现Spring Security,Spring Stomp websocket Jetty嵌入式运行
- python基础学习中要懂的知识点:反射机制
- vue3.x案例 购物车
- eval?python顺序列表模拟栈实现计算器
- mybatis mysql查询树形结构_MyBatis collection 集合嵌套查询树形节点
- java servlet,action,struts,struts2输出流中文编码问题
- FineReport10.0功能说明
- PX4模块设计之八:Ubuntu 20.04搭建FlightGear模拟器
- 【原理+代码】Python实现Topsis分析法(优劣解距离法)
- ble HCI 流控机制
- netkeeper客户端 Linux,netkeeper_for_linux
- macOS 安装lrzsz
- 100个python算法超详细讲解:递归解决分鱼问题
- java ice c_Java的Ice包接收中文乱码
- 详细理解HashMap数据结构,太齐全了!
- Intel(R)Dual Band Wireless-AC 3165网卡驱动程序出现问题,WiFi,热点和以太网无法连接
- 【沃顿商学院学习笔记】商业分析——Customer Analytics:05 营销中的新兴数据集:营销科学的未来 EMERGING DATA SETS IN MARKETING
- matlab读取心电注释.qrs文件格式,MIT-BIH ECG 心电数据的下载和读取图解 - 晨宇思远 - CSDN博客...
- 人情似纸张张薄 世事如棋局局新
热门文章
- android 判断2g 3g 4g,如何确定网络类型是2G,3G还是4G
- windows 操作手册
- Zbit ZB25VQ16ASIG 16M flash
- 2021年中国加湿器行业发展回顾及2022年行业发展趋势预测:需求规模增长,产品趋于高端化与智能化[图]
- 1.1 python中定义变量与数据类型
- 日本连出高颜值高智商机器人,美国科学家却还想靠奇葩致胜?
- JAVA弹出浏览器窗口
- 记一次2022某地HVV中的逆向分析
- (转载)Android花样Text,设置TextView的字体、颜色、超链接等
- 阿里云服务器apache/2.4.27(Unix)配置二级域名 ProxyPassMatch