```python
import random
import torch
from keras.layers import Dense, Input
from keras.models import Model
from keras.optimizers import Adam, SGD
import keras.backend as K
def huber_loss(input, target, in_keras=True):
error = input - target
quadratic_term = error * error / 2
linear_term = abs(error) - 1 / 2
use_linear_term = (abs(error) > 1.0)
if isinstance(input,torch.Tensor):
use_linear_term = use_linear_term.float()
# print(type(use_linear_term))
elif in_keras:
use_linear_term = K.cast(use_linear_term, 'float32')
# Keras won't let us multiply floats by booleans, so we explicitly cast the booleans to floats
# print(type(use_linear_term))
return use_linear_term * linear_term + (1 - use_linear_term) * quadratic_term
def set_seed(seed=1234): # 设置种子函数的方法 #设置随机种子好做对比,每次生成的随机数都是固定的这个种子可以随便设置
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
if __name__ == '__main__':
set_seed()
loss_fn = torch.nn.SmoothL1Loss(reduce=False, size_average=False)#torch 的内置huber_loss
input_ = torch.autograd.Variable(torch.randn(3,4))
target = torch.autograd.Variable(torch.randn(3,4))
loss = loss_fn(input_ , target)
print(input_ )
print(target)
print(loss)
print("huber_loss",huber_loss(input_ ,target))#算huber loss的两种写法 可以发现huber_loss(input,target)和loss_fn算出的结果是相同的
keras的网络构建
lr_br = 0.05
input_ = Input(shape=[4,5], name='input')#输出层
hidden = Dense(64, activation='relu')(input_)#隐藏层
out = Dense(3, activation='softmax')(hidden)#输出层
model = Model(inputs=input_, outputs=out, name="br-model")
sgd_br = SGD(lr=lr_br)
model.compile(loss=huber_loss, optimizer=sgd_br, metrics=['accuracy', 'mse'])
testinput_ = torch.autograd.Variable(torch.randn(4, 4, 5))#因为训练的时候输入的需要是一个batch的数据,如果输入数据和输入的大小是相等的 则会报错 expected input to have 3 dimensions, but got array with shape torch.Size([4, 5]) 多出来的一维代表这是多少个数据
predictvalue = model.predict(testinput_)#输出的尺寸是数据个数*输出的shape
print("testinput_",testinput_)
print("predictvalue",predictvalue)
这个图是huber loss不同的ρ对损失函数的惩罚程度,可以看出当ρ越小,超出±ρ的区域的惩罚变为线性的。