- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章详解MindSpore自定义模型损失函数由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
损失函数是机器学习中直接决定训练结果好坏的一个模块,该函数用于定义计算出来的结果或者是神经网络给出的推测结论与正确结果的偏差程度,偏差的越多,就表明对应的参数越差。而损失函数的另一个重要性在于会影响到优化函数的收敛性,如果损失函数的指数定义的太高,稍有参数波动就导致结果的巨大波动的话,那么训练和优化就很难收敛。一般我们常用的损失函数是mse(均方误差)和mae(平均标准差)等。那么这里我们尝试在mindspore中去自定义一些损失函数,可用于适应自己的特殊场景.
刚才提到的mse和mae等常见损失函数,mindspore中是有内置的,通过net_loss = nn.loss.mseloss()即可调用,再传入model中进行训练,具体使用方法可以参考如下拟合一个非线性函数的案例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
# test_nonlinear.py
from mindspore
import
context
import
numpy as np
from mindspore
import
dataset as ds
from mindspore
import
nn, tensor, model
import
time
from mindspore.train.callback
import
callback, lossmonitor
import
mindspore as ms
ms.common.set_seed(0)
def get_data(num, a=2.0, b=3.0, c=5.0):
for _ in range(num):
x = np.random.uniform(-1.0, 1.0)
y = np.random.uniform(-1.0, 1.0)
noise = np.random.normal(0, 0.03)
z = a * x ** 2 + b * y ** 3 + c + noise
yield np.array([[x**2], [y**3]],dtype=np.float32).reshape(1,2), np.array([z]).astype(np.float32)
def create_dataset(num_data, batch_size=16, repeat_size=1):
input_data = ds.generatordataset(list(get_data(num_data)), column_names=[
'xy'
,
'z'
])
input_data = input_data.batch(batch_size)
input_data = input_data.repeat(repeat_size)
return input_data
data_number = 160
batch_number = 10
repeat_number = 10
ds_train = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number)
class linearnet(nn.cell):
def __init__(self):
super(linearnet, self).__init__()
self.fc = nn.dense(2, 1, 0.02, 0.02)
def construct(self, x):
x = self.fc(x)
return x
start_time = time.time()
net = linearnet()
model_params = net.trainable_params()
print (
'param shape is: {}'
.format(len(model_params)))
for net_param in net.trainable_params():
print(net_param, net_param.asnumpy())
net_loss = nn.loss.mseloss()
optim = nn.momentum(net.trainable_params(), learning_rate=0.01, momentum=0.6)
model = model(net, net_loss, optim)
epoch = 1
model.train(epoch, ds_train, callbacks=[lossmonitor(10)], dataset_sink_mode=true)
for net_param in net.trainable_params():
print(net_param, net_param.asnumpy())
print (
'the total time cost is: {}s'
.format(time.time() - start_time))
|
训练的结果如下:
epoch: 1 step: 160, loss is 2.5267093 。
parameter (name=fc.weight, shape=(1, 2), dtype=float32, requires_grad=true) [[1.0694231 0.12706374]] 。
parameter (name=fc.bias, shape=(1,), dtype=float32, requires_grad=true) [5.186701] 。
the total time cost is: 8.412306308746338s 。
最终优化出来的loss值是2.5,不过在损失函数定义不同的情况下,单纯只看loss值是没有意义的。所以通常是大家统一定一个测试的标准,比如大家都用mae来衡量最终训练出来的模型的好坏,但是中间训练的过程不一定采用mae来作为损失函数.
由于python语言的灵活性,使得我们可以继承基本类和函数,只要使用mindspore允许范围内的算子,就可以实现自定义的损失函数。我们先看一个简单的案例,暂时将我们自定义的损失函数命名为l1loss:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
# test_nonlinear.py
from mindspore
import
context
import
numpy as np
from mindspore
import
dataset as ds
from mindspore
import
nn, tensor, model
import
time
from mindspore.train.callback
import
callback, lossmonitor
import
mindspore as ms
import
mindspore.ops as ops
from mindspore.nn.loss.loss
import
loss
ms.common.set_seed(0)
def get_data(num, a=2.0, b=3.0, c=5.0):
for _ in range(num):
x = np.random.uniform(-1.0, 1.0)
y = np.random.uniform(-1.0, 1.0)
noise = np.random.normal(0, 0.03)
z = a * x ** 2 + b * y ** 3 + c + noise
yield np.array([[x**2], [y**3]],dtype=np.float32).reshape(1,2), np.array([z]).astype(np.float32)
def create_dataset(num_data, batch_size=16, repeat_size=1):
input_data = ds.generatordataset(list(get_data(num_data)), column_names=[
'xy'
,
'z'
])
input_data = input_data.batch(batch_size)
input_data = input_data.repeat(repeat_size)
return input_data
data_number = 160
batch_number = 10
repeat_number = 10
ds_train = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number)
class linearnet(nn.cell):
def __init__(self):
super(linearnet, self).__init__()
self.fc = nn.dense(2, 1, 0.02, 0.02)
def construct(self, x):
x = self.fc(x)
return x
start_time = time.time()
net = linearnet()
model_params = net.trainable_params()
print (
'param shape is: {}'
.format(len(model_params)))
for net_param in net.trainable_params():
print(net_param, net_param.asnumpy())
class l1loss(loss):
def __init__(self, reduction=
"mean"
):
super(l1loss, self).__init__(reduction)
self.abs = ops.abs()
def construct(self, base, target):
x = self.abs(base - target)
return self.get_loss(x)
user_loss = l1loss()
optim = nn.momentum(net.trainable_params(), learning_rate=0.01, momentum=0.6)
model = model(net, user_loss, optim)
epoch = 1
model.train(epoch, ds_train, callbacks=[lossmonitor(10)], dataset_sink_mode=true)
for net_param in net.trainable_params():
print(net_param, net_param.asnumpy())
print (
'the total time cost is: {}s'
.format(time.time() - start_time))
|
这里自己定义的内容实际上有两个部分,一个是construct函数中的计算结果的函数,比如这里使用的是求绝对值。另外一个定义的部分是reduction参数,我们从mindspore的源码中可以看到,这个reduction函数可以决定调用哪一种计算方法,定义好的有平均值、求和、保持不变三种策略.
那么最后看下自定义的这个损失函数的运行结果:
epoch: 1 step: 160, loss is 1.8300734 。
parameter (name=fc.weight, shape=(1, 2), dtype=float32, requires_grad=true) [[ 1.2687287 -0.09565887]] 。
parameter (name=fc.bias, shape=(1,), dtype=float32, requires_grad=true) [3.7297544] 。
the total time cost is: 7.0749146938323975s 。
这里不必太在乎loss的值,因为前面也提到了,不同的损失函数框架下,计算出来的值就是不一样的,小一点大一点并没有太大意义,最终还是需要大家统一一个标准才能够进行很好的衡量和对比.
这里我们仅仅是替换了一个abs的算子为square的算子,从求绝对值变化到求均方误差,这里只是修改了一个算子,内容较为简单:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
# test_nonlinear.py
from mindspore
import
context
import
numpy as np
from mindspore
import
dataset as ds
from mindspore
import
nn, tensor, model
import
time
from mindspore.train.callback
import
callback, lossmonitor
import
mindspore as ms
import
mindspore.ops as ops
from mindspore.nn.loss.loss
import
loss
ms.common.set_seed(0)
def get_data(num, a=2.0, b=3.0, c=5.0):
for _ in range(num):
x = np.random.uniform(-1.0, 1.0)
y = np.random.uniform(-1.0, 1.0)
noise = np.random.normal(0, 0.03)
z = a * x ** 2 + b * y ** 3 + c + noise
yield np.array([[x**2], [y**3]],dtype=np.float32).reshape(1,2), np.array([z]).astype(np.float32)
def create_dataset(num_data, batch_size=16, repeat_size=1):
input_data = ds.generatordataset(list(get_data(num_data)), column_names=[
'xy'
,
'z'
])
input_data = input_data.batch(batch_size)
input_data = input_data.repeat(repeat_size)
return input_data
data_number = 160
batch_number = 10
repeat_number = 10
ds_train = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number)
class linearnet(nn.cell):
def __init__(self):
super(linearnet, self).__init__()
self.fc = nn.dense(2, 1, 0.02, 0.02)
def construct(self, x):
x = self.fc(x)
return x
start_time = time.time()
net = linearnet()
model_params = net.trainable_params()
print (
'param shape is: {}'
.format(len(model_params)))
for net_param in net.trainable_params():
print(net_param, net_param.asnumpy())
class l1loss(loss):
def __init__(self, reduction=
"mean"
):
super(l1loss, self).__init__(reduction)
self.square = ops.square()
def construct(self, base, target):
x = self.square(base - target)
return self.get_loss(x)
user_loss = l1loss()
optim = nn.momentum(net.trainable_params(), learning_rate=0.01, momentum=0.6)
model = model(net, user_loss, optim)
epoch = 1
model.train(epoch, ds_train, callbacks=[lossmonitor(10)], dataset_sink_mode=true)
for net_param in net.trainable_params():
print(net_param, net_param.asnumpy())
print (
'the total time cost is: {}s'
.format(time.time() - start_time))
|
关于更多的算子内容,可以参考下这个链接 。
(https://www.mindspore.cn/doc/api_python/zh-cn/r1.2/mindspore/mindspore.ops.html)中的内容, 。
上述代码的运行结果如下:
epoch: 1 step: 160, loss is 2.5267093 。
parameter (name=fc.weight, shape=(1, 2), dtype=float32, requires_grad=true) [[1.0694231 0.12706374]] 。
parameter (name=fc.bias, shape=(1,), dtype=float32, requires_grad=true) [5.186701] 。
the total time cost is: 6.87545919418335s 。
可以从这个结果中发现的是,计算出来的结果跟最开始使用的内置的mseloss结果是一样的,这是因为我们自定义的这个求损失函数的形式与内置的mse是吻合的.
上面的两个例子都是简单的说明了一下通过单个算子构造的损失函数,其实如果是一个复杂的损失函数,也可以通过多个算子的组合操作来进行实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
# test_nonlinear.py
from mindspore
import
context
import
numpy as np
from mindspore
import
dataset as ds
from mindspore
import
nn, tensor, model
import
time
from mindspore.train.callback
import
callback, lossmonitor
import
mindspore as ms
import
mindspore.ops as ops
from mindspore.nn.loss.loss
import
loss
ms.common.set_seed(0)
def get_data(num, a=2.0, b=3.0, c=5.0):
for _ in range(num):
x = np.random.uniform(-1.0, 1.0)
y = np.random.uniform(-1.0, 1.0)
noise = np.random.normal(0, 0.03)
z = a * x ** 2 + b * y ** 3 + c + noise
yield np.array([[x**2], [y**3]],dtype=np.float32).reshape(1,2), np.array([z]).astype(np.float32)
def create_dataset(num_data, batch_size=16, repeat_size=1):
input_data = ds.generatordataset(list(get_data(num_data)), column_names=[
'xy'
,
'z'
])
input_data = input_data.batch(batch_size)
input_data = input_data.repeat(repeat_size)
return input_data
data_number = 160
batch_number = 10
repeat_number = 10
ds_train = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number)
class linearnet(nn.cell):
def __init__(self):
super(linearnet, self).__init__()
self.fc = nn.dense(2, 1, 0.02, 0.02)
def construct(self, x):
x = self.fc(x)
return x
start_time = time.time()
net = linearnet()
model_params = net.trainable_params()
print (
'param shape is: {}'
.format(len(model_params)))
for net_param in net.trainable_params():
print(net_param, net_param.asnumpy())
class l1loss(loss):
def __init__(self, reduction=
"mean"
):
super(l1loss, self).__init__(reduction)
self.square = ops.square()
def construct(self, base, target):
x = self.square(self.square(base - target))
return self.get_loss(x)
user_loss = l1loss()
optim = nn.momentum(net.trainable_params(), learning_rate=0.01, momentum=0.6)
model = model(net, user_loss, optim)
epoch = 1
model.train(epoch, ds_train, callbacks=[lossmonitor(10)], dataset_sink_mode=true)
for net_param in net.trainable_params():
print(net_param, net_param.asnumpy())
print (
'the total time cost is: {}s'
.format(time.time() - start_time))
|
这里使用的函数是两个平方算子,也就是四次方的均方误差,运行结果如下:
epoch: 1 step: 160, loss is 16.992222 。
parameter (name=fc.weight, shape=(1, 2), dtype=float32, requires_grad=true) [[0.14460069 0.32045612]] 。
parameter (name=fc.bias, shape=(1,), dtype=float32, requires_grad=true) [5.6676607] 。
the total time cost is: 7.253541946411133s 。
在实际的运算过程中,我们肯定不能够说提升损失函数的幂次就一定能够提升结果的优劣,但是通过多种基础算子的组合,理论上说我们在一定的误差允许范围内,是可以实现任意的一个损失函数(通过泰勒展开取截断项)的.
方才提到这里面自定义损失函数的两个重点,一个是上面三个章节中所演示的construct函数的重写,这部分实际上是重新设计损失函数的函数表达式。另一个是reduction的自定义,这部分关系到不同的单点损失函数值之间的关系。举个例子来说,如果我们将reduction设置为求和,那么get_loss()这部分的函数内容就是把所有的单点函数值加起来返回一个最终的值,求平均值也是类似的。那么通过自定义一个新的get_loss()函数,我们就可以实现更加灵活的一些操作,比如我们可以选择将所有的结果乘起来求积而不是求和(只是举个例子,大部分情况下不会这么操作)。在python中要重写这个函数也容易,就是在继承父类的自定义类中定义一个同名函数即可,但是注意我们最好是保留原函数中的一些内容,在原内容的基础上加一些东西,冒然改模块有可能导致不好定位的运行报错.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
# test_nonlinear.py
from mindspore
import
context
import
numpy as np
from mindspore
import
dataset as ds
from mindspore
import
nn, tensor, model
import
time
from mindspore.train.callback
import
callback, lossmonitor
import
mindspore as ms
import
mindspore.ops as ops
from mindspore.nn.loss.loss
import
loss
ms.common.set_seed(0)
def get_data(num, a=2.0, b=3.0, c=5.0):
for _ in range(num):
x = np.random.uniform(-1.0, 1.0)
y = np.random.uniform(-1.0, 1.0)
noise = np.random.normal(0, 0.03)
z = a * x ** 2 + b * y ** 3 + c + noise
yield np.array([[x**2], [y**3]],dtype=np.float32).reshape(1,2), np.array([z]).astype(np.float32)
def create_dataset(num_data, batch_size=16, repeat_size=1):
input_data = ds.generatordataset(list(get_data(num_data)), column_names=[
'xy'
,
'z'
])
input_data = input_data.batch(batch_size)
input_data = input_data.repeat(repeat_size)
return input_data
data_number = 160
batch_number = 10
repeat_number = 10
ds_train = create_dataset(data_number, batch_size=batch_number, repeat_size=repeat_number)
class linearnet(nn.cell):
def __init__(self):
super(linearnet, self).__init__()
self.fc = nn.dense(2, 1, 0.02, 0.02)
def construct(self, x):
x = self.fc(x)
return x
start_time = time.time()
net = linearnet()
model_params = net.trainable_params()
print (
'param shape is: {}'
.format(len(model_params)))
for net_param in net.trainable_params():
print(net_param, net_param.asnumpy())
class l1loss(loss):
def __init__(self, reduction=
"mean"
, config=true):
super(l1loss, self).__init__(reduction)
self.square = ops.square()
self.config = config
def construct(self, base, target):
x = self.square(base - target)
return self.get_loss(x)
def get_loss(self, x, weights=1.0):
print (
'the data shape of x is: '
, x.shape)
input_dtype = x.dtype
x = self.cast(x, ms.common.dtype.float32)
weights = self.cast(weights, ms.common.dtype.float32)
x = self.mul(weights, x)
if
self.reduce
and
self.average:
x = self.reduce_mean(x, self.get_axis(x))
if
self.reduce
and
not
self.average:
x = self.reduce_sum(x, self.get_axis(x))
if
self.config:
x = self.reduce_mean(x, self.get_axis(x))
weights = self.cast(-1.0, ms.common.dtype.float32)
x = self.mul(weights, x)
x = self.cast(x, input_dtype)
return x
user_loss = l1loss()
optim = nn.momentum(net.trainable_params(), learning_rate=0.01, momentum=0.6)
model = model(net, user_loss, optim)
epoch = 1
model.train(epoch, ds_train, callbacks=[lossmonitor(10)], dataset_sink_mode=true)
for net_param in net.trainable_params():
print(net_param, net_param.asnumpy())
print (
'the total time cost is: {}s'
.format(time.time() - start_time))
|
上述代码就是一个简单的案例,这里我们所做的操作,仅仅是把之前均方误差的求和改成了求和之后取负数。还是需要再强调一遍的是,虽然我们定义的函数是非常简单的内容,但是借用这个方法,我们可以更加灵活的去按照自己的设计定义一些定制化的损失函数。上述代码的执行结果如下:
the data shape of x is: 。
(10, 10, 1) 。
... 。
the data shape of x is: 。
(10, 10, 1) 。
epoch: 1 step: 160, loss is -310517200.0 。
parameter (name=fc.weight, shape=(1, 2), dtype=float32, requires_grad=true) [[-6154.176 667.4569]] 。
parameter (name=fc.bias, shape=(1,), dtype=float32, requires_grad=true) [-16418.32] 。
the total time cost is: 6.681089878082275s 。
一共打印了160个the data shape of x is...,这是因为我们在划分输入的数据集的时候,选择了将160个数据划分为每个batch含10个元素的模块,那么一共就有16个batch,又对这16个batch重复10次,那么就是一共有160个batch,计算损失函数时是以batch为单位的,但是如果只是计算求和或者求平均值的话,不管划分多少个batch结果都是一致的.
以上就是详解mindspore自定义模型损失函数的详细内容,更多关于mindspore自定义模型损失函数的资料请关注我其它相关文章! 。
原文链接:https://www.cnblogs.com/dechinphy/p/msloss.html 。
最后此篇关于详解MindSpore自定义模型损失函数的文章就讲到这里了,如果你想了解更多关于详解MindSpore自定义模型损失函数的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!