本文主要是采用麻雀算法SSA优化LSTM超参数
麻雀搜索算法是2020提出的一种新的优化算法,在此不对具体原理进行分析,针对代码实操.
麻雀算法代码简介
class SSA():
def __init__(self, func, n_dim=None, pop_size=20, max_iter=50, lb=-512, ub=512, verbose=False):
self.func = func
self.n_dim = n_dim # dimension of particles, which is the number of variables of func
self.pop = pop_size # number of particles
P_percent = 0.2 # # 生产者的人口规模占总人口规模的20%
D_percent = 0.1 # 预警者的人口规模占总人口规模的10%
self.pNum = round(self.pop * P_percent) # 生产者的人口规模占总人口规模的20%
self.warn = round(self.pop * D_percent) # 预警者的人口规模占总人口规模的10%
self.max_iter = max_iter # max iter
self.verbose = verbose # print the result of each iter or not
self.lb, self.ub = np.array(lb) * np.ones(self.n_dim), np.array(ub) * np.ones(self.n_dim)
assert self.n_dim == len(self.lb) == len(self.ub), 'dim == len(lb) == len(ub) is not True'
assert np.all(self.ub > self.lb), 'upper-bound must be greater than lower-bound'
self.X = np.random.uniform(low=self.lb, high=self.ub, size=(self.pop, self.n_dim))
self.Y = [self.func(self.X[i]) for i in range(len(self.X))] # y = f(x) for all particles
self.pbest_x = self.X.copy() # personal best location of every particle in history
self.pbest_y = [np.inf for i in range(self.pop)] # best image of every particle in history
self.gbest_x = self.pbest_x.mean(axis=0).reshape(1, -1) # global best location for all particles
self.gbest_y = np.inf # global best y for all particles
self.gbest_y_hist = [] # gbest_y of every iteration
self.update_pbest()
self.update_gbest()
#
# record verbose values
self.record_mode = False
self.record_value = {'X': [], 'V': [], 'Y': []}
self.best_x, self.best_y = self.gbest_x, self.gbest_y # history reasons, will be deprecated
self.idx_max = 0
self.x_max = self.X[self.idx_max, :]
self.y_max = self.Y[self.idx_max]
def cal_y(self, start, end):
# calculate y for every x in X
for i in range(start, end):
self.Y[i] = self.func(self.X[i])
# return self.Y
def update_pbest(self):
'''
personal best
'''
for i in range(len(self.Y)):
if self.pbest_y[i] > self.Y[i]:
self.pbest_x[i] = self.X[i]
self.pbest_y[i] = self.Y[i]
def update_gbest(self):
idx_min = self.pbest_y.index(min(self.pbest_y))
if self.gbest_y > self.pbest_y[idx_min]:
self.gbest_x = self.X[idx_min, :].copy()
self.gbest_y = self.pbest_y[idx_min]
def find_worst(self):
self.idx_max = self.Y.index(max(self.Y))
self.x_max = self.X[self.idx_max, :]
self.y_max = self.Y[self.idx_max]
def update_finder(self):
r2 = np.random.rand(1) # 预警值
self.idx = sorted(enumerate(self.Y), key=lambda x: x[1])
self.idx = [self.idx[i][0] for i in range(len(self.idx))]
# 这一部位为发现者(探索者)的位置更新
if r2 < 0.8: # 预警值较小,说明没有捕食者出现
for i in range(self.pNum):
r1 = np.random.rand(1)
self.X[self.idx[i], :] = self.X[self.idx[i], :] * np.exp(-(i) / (r1 * self.max_iter)) # 对自变量做一个随机变换
self.X = np.clip(self.X, self.lb, self.ub) # 对超过边界的变量进行去除
# X[idx[i], :] = Bounds(X[idx[i], :], lb, ub) # 对超过边界的变量进行去除
# fit[sortIndex[0, i], 0] = func(X[sortIndex[0, i], :]) # 算新的适应度值
elif r2 >= 0.8: # 预警值较大,说明有捕食者出现威胁到了种群的安全,需要去其它地方觅食
for i in range(self.pNum):
Q = np.random.rand(1) # 也可以替换成 np.random.normal(loc=0, scale=1.0, size=1)
self.X[self.idx[i], :] = self.X[self.idx[i], :] + Q * np.ones(
(1, self.n_dim)) # Q是服从正态分布的随机数。L表示一个1×d的矩阵
self.X = np.clip(self.X, self.lb, self.ub) # 对超过边界的变量进行去除
# X[idx[i], :] = Bounds(X[sortIndex[0, i], :], lb, ub)
# fit[sortIndex[0, i], 0] = func(X[sortIndex[0, i], :])
self.cal_y(0, self.pNum)
def update_follower(self):
# 这一部位为加入者(追随者)的位置更新
for ii in range(self.pop - self.pNum):
i = ii + self.pNum
A = np.floor(np.random.rand(1, self.n_dim) * 2) * 2 - 1
best_idx = self.Y[0:self.pNum].index(min(self.Y[0:self.pNum]))
bestXX = self.X[best_idx, :]
if i > self.pop / 2:
Q = np.random.rand(1)
self.X[self.idx[i], :] = Q * np.exp((self.x_max - self.X[self.idx[i], :]) / np.square(i))
else:
self.X[self.idx[i], :] = bestXX + np.dot(np.abs(self.X[self.idx[i], :] - bestXX),
1 / (A.T * np.dot(A, A.T))) * np.ones((1, self.n_dim))
self.X = np.clip(self.X, self.lb, self.ub) # 对超过边界的变量进行去除
# X[self.idx[i],:] = Bounds(X[self.idx[i],lb,ub)
# fit[self.idx[i],0] = func(X[self.idx[i], :])
self.cal_y(self.pNum, self.pop)
def detect(self):
arrc = np.arange(self.pop)
c = np.random.permutation(arrc) # 随机排列序列
b = [self.idx[i] for i in c[0: self.warn]]
e = 10e-10
for j in range(len(b)):
if self.Y[b[j]] > self.gbest_y:
self.X[b[j], :] = self.gbest_y + np.random.rand(1, self.n_dim) * np.abs(self.X[b[j], :] - self.gbest_y)
else:
self.X[b[j], :] = self.X[b[j], :] + (2 * np.random.rand(1) - 1) * np.abs(
self.X[b[j], :] - self.x_max) / (self.func(self.X[b[j]]) - self.y_max + e)
# X[sortIndex[0, b[j]], :] = Bounds(X[sortIndex[0, b[j]], :], lb, ub)
# fit[sortIndex[0, b[j]], 0] = func(X[sortIndex[0, b[j]]])
self.X = np.clip(self.X, self.lb, self.ub) # 对超过边界的变量进行去除
self.Y[b[j]] = self.func(self.X[b[j]])
def run(self, max_iter=None):
self.max_iter = max_iter or self.max_iter
for iter_num in range(self.max_iter):
self.update_finder() # 更新发现者位置
self.find_worst() # 取出最大的适应度值和最差适应度的X
self.update_follower() # 更新跟随着位置
self.update_pbest()
self.update_gbest()
self.detect()
self.update_pbest()
self.update_gbest()
self.gbest_y_hist.append(self.gbest_y)
return self.best_x, self.best_y
def build_model(neurons1, neurons2, dropout):
X_train, y_train, X_test, y_test = process_data()
# X_train, y_train = create_dataset(X_train, y_train, steps)
# X_test, y_test = create_dataset(X_test, y_test, steps)
nb_features = X_train.shape[2]
input1 = X_train.shape[1]
model1 = Sequential()
model1.add(LSTM(
input_shape=(input1, nb_features),
units=neurons1,
return_sequences=True))
model1.add(Dropout(dropout))
model1.add(LSTM(
units=neurons2,
return_sequences=False))
model1.add(Dropout(dropout))
model1.add(Dense(units=1))
model1.add(Activation("linear"))
model1.compile(loss='mse', optimizer='Adam', metrics='mae')
return model1, X_train, y_train, X_test, y_test
if __name__ == '__main__':
'''
神经网络第一层神经元个数
神经网络第二层神经元个数
dropout比率
batch_size
'''
neurons1 = 64
neurons2 = 64
dropout = 0.01
batch_size = 32
model, X_train, y_train, X_test, y_test = build_model(neurons1, neurons2, dropout)
history1 = model.fit(X_train, y_train, epochs=150, batch_size=batch_size, validation_split=0.2, verbose=1,
callbacks=[EarlyStopping(monitor='val_loss', patience=9, restore_best_weights=True)])
# 测试集预测
y_score = model.predict(X_test)
# 反归一化
y_score = scaler.inverse_transform(y_score.reshape(-1, 1))
y_test = scaler.inverse_transform(y_test.reshape(-1, 1))
print("==========evaluation==============\n")
from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error #平方绝对误差
import math
MAE = mean_absolute_error(y_test, y_score)
print('MAE: %.4f ' % MAE)
RMSE = math.sqrt(mean_squared_error(y_test, y_score))
print('RMSE: %.4f ' % (RMSE))
备注:
需要源代码和数据集,或者想要沟通交流,请私聊,谢谢.
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano
我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use
对于作为String#tr参数的单引号字符串文字中反斜杠的转义状态,我觉得有些神秘。你能解释一下下面三个例子之间的对比吗?我特别不明白第二个。为了避免复杂化,我在这里使用了'd',在双引号中转义时不会改变含义("\d"="d")。'\\'.tr('\\','x')#=>"x"'\\'.tr('\\d','x')#=>"\\"'\\'.tr('\\\d','x')#=>"x" 最佳答案 在tr中转义tr的第一个参数非常类似于正则表达式中的括号字符分组。您可以在表达式的开头使用^来否定匹配(替换任何不匹配的内容)并使用例如a-f来匹配一
我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些
目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非