基于深度学习淡水鱼体重智能识别模型研究
工作原理为:首先对大众淡水鱼图片进行数据清洗并做标签分类,之后基于残差网络ResNet50模型进行有监督的分类识别训练,获取识别模型。其次通过搭建回归模型设计出体重模型,对每一类淡水鱼分别拟合出对应的回归方程,将获取的某类淡水鱼轮廓面积与质量间的数据集合并为新数据集,之后对此类淡水鱼进行轮廓面积与质量间的深度学习回归训练,最终拟合出此类淡水鱼类的体重回归方程;最后在使用时当鱼类经过摄影区时获取较为完整的鱼类平面图,将获取到的鱼类图像进行背景模糊、自适应分割、轮廓标记等方式获取鱼类轮廓,通过搭建的识别模型获得此鱼类种类后做类别标记并计算轮廓面积,最终通过此类淡水鱼的类别去使用特有的体重模型获取此个体的质量。
分类识别模型训练中总共使用了32种淡水鱼,总计9253张图片,微调清洗后投入6120张图片,各类淡水鱼识别率达到95%以上,其中亚洲鲈鱼识别率为100%。体重模型以亚洲鲈鱼为例,此课题拟合了445份质量与轮廓面面积数据,最终计算体重偏差多数小于5%。
使用经典的ResNet-50作为预训练模型来Finetune,对32种淡水鱼类进行分类,由于样品数量较大,随机抽取样品进行迁移学习,测试结果准确率100%。并做鱼类重量计算。
1.Fish数据集
实验材料包括三份淡水鱼数据,第一份为来自爱发电社区的淡水鱼数据集,包含 30 类约 3000 张淡水鱼图片。 第二份为“FishImgDataset”,来自著名数据集网站“kaggle”,分为 31 个种类大约 8000 多张日常生活中常见的淡水鱼图片。 第三份为“BarraRulerDataset445-master”,完整保存了 445 份鲈鱼的原始照片以及其体重数据。
2.本实验的任务
本实践选取32种鱼类数据随机抽取数据进行迁移学习训练。 由于个别样品数量大,使微调时长变长,微调也不需要这么多样本,因此对超过200个的样品进行随机抽样,抽样200个,然后和样品数量少于200的样品合并,组成新的数据集,然后在新的数据集里随机抽样形成训练集、测试集、验证集,数据无重复,使用使用pandas 的进行数据处理,过程优雅大方。,最后Finetune训练及预测结果的输出。
3.经典的ResNet-50作为预训练模型
使用经典的ResNet-50作为预训练模型来Finetune,对32种淡水鱼类进行分类,由于样品数量较大,随机抽取样品进行迁移学习,测试结果准确率高。
查看当前挂载的数据集目录, 该目录下的变更重启环境后会自动还原
# View dataset directory. This directory will be recovered automatically after resetting environment.
!ls /home/aistudio/data
查看工作区文件, 该目录下的变更将会持久保存. 请及时清理不必要的文件, 避免加载过慢.
# View personal work directory. All changes under this directory will be kept even after reset. Please clean unnecessary files in time to speed up environment loading.
!ls /home/aistudio/work
如果需要进行持久化安装, 需要使用持久化路径, 如下方代码示例:
# If a persistence installation is required, you need to use the persistence path as the following:
!mkdir /home/aistudio/external-libraries码片
同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可:
# Also add the following code, so that every time the environment (kernel) starts, just run the following code:
import sys
CPU环境启动请务必执行该指令
%set_env CPU_NUM=2 代码片
安装paddlehub
!pip install paddlehub==1.6.0 -i https://pypi.tuna.tsinghua.edu.cn/simple
!hub install ernie
import os
import pandas as pd #用列表生成 DataFrame,便于到出text文档。
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image, ImageDraw, ImageFont #显示图片
```python
!mkdir data/fish_pic
4.解压数据
!unzip -o picture/last.zip -d picture/newfish
!unzip -o data/data212523/data.zip -d data/fish_pic
5.制作数据准备函数。
5.1 32种鱼类对应的学名
生成类别用于结果判定。
fish_name=['Bangus','Big Head Carp','Black Spotted Barb','Catfish','Climbing Perch','Fourfinger Threadfin','Freshwater Eel','Glass Perchlet','Goby','Gold Fish','Gourami','Grass Carp','Green Spotted Puffer','Indian Carp','Indo-Pacific Tarpon','Jaguar Gapote','Janitor Fish','Knifefish','Long-Snouted Pipefish','Mosquito Fish','Mudfish','Mullet','Pangasius','Perch','Scat Fish','Silver Barb','Silver Carp','Silver Perch','Snakehead','Tenpounder','Tilapia','bass']
fish_name
5.2 生成鱼类名字字典、标签字典
name_list=[] #生成标签文档
with open ('data/label_list.txt','w+') as f:for i in range(1,33):name_list.append('fish_'+str(i))f.write('fish_'+str(i)+'\n')name_dict={b:a for a,b in enumerate(name_list)}
name_dict
real_name={a:b for a,b in zip(name_list,fish_name)}
real_name
5.3 生成图片路径和标签列表对应的字典 ,用于生成DataFrame
#此函数生成包括路径和标签的字典,可以直接生成DataFrame,后面是用路径列表生成DataFrame.
# def data_list():
# path="data/fish_pic/fish_data/fish_image23" #图片所在文件夹
# address_list = [] #图片地址列表
# label_list = [] #标签列表
# for root, dirs, files in os.walk(path, topdown=False):
# for name in files:
# address = os.path.join(root, name) #获取图片路径
# address_list.append(address)
# label = address.split('/')[4] #路径分割后,截取目录名即为标记名,开始的时候大脑里转的是map,lambda,还是apply!一直出不来 为啥我不早点想出来呢,
# label_list.append(name_dict.get(label)) #截取目录名对应的标注
# return {'address':address_list,'label':label_list} #生成字典
# data_list()
5.4 生成图片路径列表 ,用于生成DataFrame
#生成图片路径列表
def data_list():path="data/fish_pic/fish_data/fish_image23" #图片所在文件夹path_list = [] #图片地址列表 for root, dirs, files in os.walk(path, topdown=False):for name in files:path = os.path.join(root, name) #获取图片路径path_list.append(path) return path_list #生成路径列表
#data_list()
5.5 用列表生成 DataFrame,便于到出text文档。
df = pd.DataFrame(data_list(),columns=['filepath']) #生成数据框。
df['filepath'] = df.filepath.str[5:] #按要求产生相对路径。只要工作目录下的相对路径 。
df['label']=df.filepath.apply(lambda x:x.split('/')[3]).map(name_dict) #用映射生成标签df.head()
5.6 简单出个图确认前面的工作是否正常。
grouped=df.label.value_counts() #查看样品分布情况
type(grouped)
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
plt.figure(figsize=(10,2))# 这里是调节横坐标的倾斜度,rotation是度数,以及设置刻度字体大小
plt.xticks(rotation=45,fontsize=10)
plt.yticks(fontsize=10)
plt.title('''Fish Category''',fontsize = 20)
plt.bar(grouped.index,grouped,color='r',tick_label=name_list,facecolor='#9999ff',edgecolor='white')
plt.savefig('/home/aistudio/work/bar_result.jpg')
# 可见我们数据很不整齐,全部投入使用吃力不讨好,因此,考虑随机抽样参与训练。
例:
5.7 通过分析 样品个数大于两百的分类情况。
grouped[grouped.values>200].sum() #
grouped[grouped.values<200].sum()
5.8 随机采样,形成新的数据集
由于个别样品数量大,使微调时长边长,微调也不需要这么多样本,因此对超过200个的样品进行随机抽样,抽样200个,然后和样品数量少于200的样品合并,组成新的数据集,进行后续的Finetune训练。
1、先找出样品个数大于200样品标签。
2、提取样品数量少于200个的样品,形成新的数据集。
3、从样品个数多于200个的品类种随机抽取200样品,加入到上述数据集。
4、最后共获得6120个样品的数据集。label_index = grouped[grouped.values>200].index # 样品数量大于200个标签值(label标签对应的 值)extract=df.loc[~df['label'].isin(label_index)] #取非,样品数少于200的样品,全作为工作样品,
for i in label_index:#d=df.loc[df['label']==i].sample(200)d=df[df['label']==i].sample(200) #样品数量大于200个的样品随机抽取200个作为工作样品。extract=extract.append(d) #分别补充至
len( extract)
#新数据的数据分布。
grouped=extract.label.value_counts() #样本数量统计
#plt.bar(grouped.index,grouped)
plt.figure(figsize=(10,2))
plt.title('''New Fish Category''',fontsize = 20)
grouped.plot(kind='bar')
<matplotlib.axes._subplots.AxesSubplot at 0x7f935138c890>
/opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/font_manager.py:1331: UserWarning: findfont: Font family ['sans-serif'] not found. Falling back to DejaVu Sans(prop.get_family(), self.defaultFamily[fontext]))
例:
5.9 样品列表生成,关键操作
样品数据框随机打乱,按9:1比例随机生成 测试集、验证集、训练集列表文档。
df_new=extract.copy() #样品数据框随机打乱,按9:1比例生成 测试集,验证集,训练集列表文档。
df_new = df_new.sample(frac=1.0) #打乱数据
df_validate = df_new.sample(frac=0.1) #取同数量样本作为验证集
df_new.drop(index=df_validate.index,inplace=True) #去除测试集
df_test = df_new.sample(20) #随机抽取20个样本作为测试集
df_train = df_new.drop(index=df_test.index) #剩下的为训练集
len(df_train.index)
5.10 生成数据列表文件
df_test['filepath'] = 'data/'+df_test['filepath'] #测试集已跳出 深度学习微调环境需要补充完整路径,是个坑。
#df_test.to_csv('data/test_list.txt', sep=' ', index=0,header=0) #导出 验证集列表
df_validate.to_csv('data/validate_list.txt', sep=' ', index=0,header=0) #导出 验证集列表
df_train.to_csv('data/train_list.txt', sep=' ', index=0,header=0) #导出 训练集列表
我们来看看 我们数据图片都长什么样子的。
import matplotlib.pyplot as plt
from PIL import Image, ImageDraw, ImageFont
test_img = df_test.sample(1)['filepath'].tolist()[0] #我们就从测试集里面先抽一张出来看看(提取路径)img = Image.open(test_img).resize((256,256)) # 放大来看看!
print(img.format,img.size) # 输出图片基本信息# draw = ImageDraw.Draw(img)
# font=ImageFont.truetype('simhei.ttf',30)
# draw.text((20,20),'正确',(100,000,100), font=font)
plt.figure(figsize=(10,10))
plt.imshow(img)
6. 基于ResNet50,去组建适合于我们本次实验的My_ResNet50残差网络
1.选取ResNet_50的V2般本作为模型引入。
2.进行数据引入,即将我们之前设计的txt文件引入。
3.生成数据读取器。
4.调整适合的配置
5.微调原ResNet模型为二分类模型
6.训练迭代
7.预测
8.导出结果列表
import paddlehub as hub
6.1 模型引入
#resnet50要远好于其它的类型,在训练时表现更稳定,收敛更快。损失值相比较的话,resnet50更少一点,所以要较好一些。若是较为复杂数据集情况下可以选择resnet152
#在本次实验中resnet152训练较慢且准确度大约处于70%,而resnet50训练速度较快且识别的准确率在90%以上。
#同时resnet50还有“v1”、“v1.5”、“v2”版本,v2的表现最好
module = hub.Module(name="resnet_v2_50_imagenet")
# module = hub.Module(name="resnet_v2_18_imagenet")
# module = hub.Module(name="resnet_v2_34_imagenet")
# module = hub.Module(name="resnet_v2_101_imagenet")
#module = hub.Module(name="resnet_v2_152_imagenet")
6.2 数据准备
着需要加载图片数据集。我们使用自定义的数据进行体验
from paddlehub.dataset.base_cv_dataset import BaseCVDatasetclass DemoDataset(BaseCVDataset): def __init__(self): # 数据集存放位置self.dataset_dir = "data"super(DemoDataset, self).__init__(base_path=self.dataset_dir,train_list_file="train_list.txt",validate_list_file="validate_list.txt",#test_list_file="test_list.txt",label_list_file="label_list.txt",)
dataset = DemoDataset()
!unzip -oq /home/aistudio/data/data212523/data.zip
6.3 生成数据读取器
接着生成一个图像分类的reader,reader负责将dataset的数据进行预处理,接着以特定格式组织并输入给模型进行训练。
当我们生成一个图像分类的reader时,需要指定输入图片的大小。
ata_reader = hub.reader.ImageClassificationReader(image_width=module.get_expected_image_width(),image_height=module.get_expected_image_height(),images_mean=module.get_pretrained_images_mean(),images_std=module.get_pretrained_images_std(),dataset=dataset)
6.4 调整适合的配置
在进行Finetune前,我们可以设置一些运行时的配置,例如如下代码中的配置,表示:
use_cuda:设置为False表示使用CPU进行训练。如果您本机支持GPU,且安装的是GPU版本的PaddlePaddle,我们建议您将这个选项设置为True;
epoch:迭代轮数;
batch_size:每次训练的时候,给模型输入的每批数据大小为32,模型训练时能够并行处理批数据,因此batch_size越大,训练的效率越高,但是同时带来了内存的负荷,过大的batch_size可能导致内存不足而无法训练,因此选择一个合适的batch_size是很重要的一步;
log_interval:每隔10 step打印一次训练日志;
eval_interval:每隔50 step在验证集上进行一次性能评估;
checkpoint_dir:将训练的参数和数据保存到cv_finetune_turtorial_demo目录中;
strategy:使用DefaultFinetuneStrategy策略进行finetune;
更多运行配置,请查看RunConfig
同时PaddleHub提供了许多优化策略,如AdamWeightDecayStrategy、ULMFiTStrategy、DefaultFinetuneStrategy等,详细信息参见策略
config = hub.RunConfig(use_cuda= True, #是否使用GPU训练,默认为False,高级算力环境用True,cpu环境写True会报错;num_epoch=5, #Fine-tune的轮数,cpu 环境用3玩玩就好,高级算力可以试试10;checkpoint_dir="cv_finetune_turtorial_demo",#模型checkpoint保存路径, 若用户没有指定,程序会自动生成;batch_size=3, #训练的批大小,如果使用GPU,请根据实际情况调整batch_size;#eval_interval=10, log_interval=20, #模型评估的间隔,默认每100个step评估一次验证集;strategy=hub.finetune.strategy.DefaultFinetuneStrategy()) #Fine-tune优化策略;
6.5 组建Finetune Task,微调原ResNet模型为二分类模型
有了合适的预训练模型和准备要迁移的数据集后,我们开始组建一个Task。 由于该数据设置是一个二分类的任务,而我们下载的分类module是在ImageNet数据集上训练的千分类模型,所以我们需要对模型进行简单的微调,把模型改造为一个二分类模型: 获取module的上下文环境,包括输入和输出的变量,以及Paddle Program; 从输出变量中找到特征图提取层feature_map; 在feature_map后面接入一个全连接层,生成Task;
input_dict, output_dict, program = module.context(trainable=True)
img = input_dict["image"]
feature_map = output_dict["feature_map"]
feed_list = [img.name]task = hub.ImageClassifierTask(data_reader=data_reader,feed_list=feed_list,feature=feature_map,num_classes=dataset.num_labels,config=config)
6.6 开始训练迭代
我们选择finetune_and_eval接口来进行模型训练,这个接口在finetune的过程中,会周期性的进行模型效果的评估,以便我们了解整个训练过程的性能变化。
run_states = task.finetune_and_eval()
6.7 预测
当Finetune完成后,我们使用模型来进行预测,先通过以下命令来获取测试的图片
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import pandas as pd
from PIL import ImageEnhance
#开始时清除上次遗留下来的文件保存值
Notee=open('data/jisuan.txt',mode='a')
Notee.truncate(0)with open("zhongliang/test.txt","r") as f:filepath = f.readlines()data =[filepath[i].split(" ")[0] for i in range(10)]
#print("22222222222222222",data)label_map = dataset.label_dict()
index = 0
run_states = task.predict(data=data)
results = [run_state.run_results for run_state in run_states]
address_dict={}
# address=[]
# label=[]
#打开文件“jisuan.txt”,用于保存得到的结果(仅仅数字)
Note=open('data/jisuan.txt',mode='a')
for batch_result in results:print("6666",batch_result)batch_result = np.argmax(batch_result, axis=2)[0]print("7777",batch_result)for result in batch_result:index += 1dataw = 1+int(result)Note.write(str(dataw)) #写数据,将识别的鱼类序号记录起来Note.write("\n")result = label_map[result]address_dict[data[index - 1]] = result# address.append(data[index - 1])# label.append(result)print("input %i is %s, and the predict result is %s" %(index, data[index - 1], result))if data[index - 1].split('/')[4]== result:print('识别正确')plt.figure(dpi=150)test_img = data[index - 1] #提取路径img = Image.open(test_img).resize((256,256))img=ImageEnhance.Contrast(img).enhance(5)txt=real_name.get(result)plt.title('Name: '+txt) # draw = ImageDraw.Draw(img)*# font=ImageFont.truetype('simhei.ttf',10)*# draw.text((20,20),txt,(0,0,0), font=font)*plt.imshow(img)else:print('识别不正确')
6.8 最后还可导出结果列表
import pandas as pd
df=pd.DataFrame.from_dict(address_dict,orient='index')
df = df.reset_index()
print(df)
df.columns=['addr','lab']
df.to_csv('data/result.txt',sep=' ',index=0,header=0) #导出结果,跟test_list比较下,是否一致。
# pip install scikit-image
! pip install scikit-image -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
# ! pip install scikit-image
7. 以下为获取k,b系数,以及计算需要计算的鱼质量
通过公式“y=kx+b”来获取质量,其中y为质量,k为系数,不同种类淡水鱼有不同的系数,x为需要计算的某条鱼的轮廓面积,b为增益系数。 1.首先获取这一类淡水鱼的数据集中的轮廓面积,并将其单独存放于weight.txt文件中。 2.将其轮廓面积与对应的体重合并到jiegou.txt文件作为新的训练数据集。 3.将新数据集转换为表格形式并做数据展示,通过折线图可以清晰的看到,轮廓面积和质量之间有一定的线性关系。 4.通过最小二乘法进行线性回归,最终拟合并得到这一类淡水鱼的k、b值。
#获取所有图片的轮廓面积
from PIL import Image
import PIL.ImageOps
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from skimage.io import imsave
from PIL import ImageEnhance
import cv2
Notee=open('zhongliang/lunkuo.txt',mode='a')
Notee.truncate(0)with open("zhongliang/dedaolunkuo.txt","r") as f:filepath = f.readlines()data =[filepath[i].split(" ")[0] for i in range(445)]
for number in range(0,445):#背景转化为黑色#in_path = "data/fish_pic/fish_data/fish_image23/fish_3/300.jpg"xuhao = 0 #这里为需要计算的图片质量序号,(0——9)in_path = data[number]print('path is : '+data[number])dizhi="zhongliang/1.jpg"out_path = dizhiout_path_area = "zhongliang/2.jpg"Img = cv2.imread(str(in_path))Img2 = np.array(Img, copy=True)white_px = np.asarray([255, 255, 255])black_px = np.asarray([0 , 0 , 0 ])(row, col, _) = Img.shapefor r in range(row):for c in range(col):px = Img[r][c]if all(px == white_px):Img2[r][c] = black_pximsave(out_path, Img2)#对转化后的图片进行描边mat_img = cv2.imread(out_path)mat_img2 = cv2.imread(out_path,cv2.CV_8UC1)#cv2.imshow("Initial image",mat_img)#cv2.waitKey(0)#自适应分割dst = cv2.adaptiveThreshold(mat_img2,210,cv2.BORDER_REPLICATE,cv2.THRESH_BINARY_INV,3,10)#提取轮廓contours,heridency = cv2.findContours(dst,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)#标记轮廓cv2.drawContours(mat_img,contours,-1,(255,0,255),3)imsave(out_path_area, mat_img)#计算轮廓面积area = 0for i in contours:area += cv2.contourArea(i)area*=100print("area is :",area)def MY_ConTourArea(cnt): #传入一个轮廓rect = cv2.minAreaRect(cnt) #最小外接矩形box = cv2.boxPoints(rect)box = np.int0(box)return cv2.contourArea(box)#cv2.contourArea()底层使用的是格林公式,对边界上的所有像素点没有相加myarea = 0for i in contours:myarea += MY_ConTourArea(i)myarea/=2myarea += areaprint("myarea is :",myarea)Note=open('zhongliang/lunkuo.txt',mode='a')Note.write(str(area)) #写数据Note.write("\n")
pip install xlwt
# # 修改合适txt,只使用一次# # 需要修改的txt文件
# filename = r"zhongliang/weight.txt"
# # 重新保存的txt文件
# new_filename = r"zhongliang/NewWeight.txt"
# # 打开需要修改的和重新保存的txt文件
# with open(filename,encoding="utf-8") as f1, open(new_filename,"w",encoding="utf-8") as f2:
# for line in f1:
# new_line = line[4:] # [:-3] 表示后三个
# f2.write(new_line)
# f1.close()
# f2.close()
#合并两个txt,以经有合并后的“jiegou.txt”了,就不需要再进行合并
import sys
import osNotee=open('zhongliang/hebing.txt',mode='a')
Notee.truncate(0)f1=open("zhongliang/lunkuo.txt","r")
line1 = f1.read().splitlines()
f2 = open("zhongliang/Weight.txt","r")
line2 = f2.read().splitlines()
list = []
for i in range(0,len(line1)):a =(line1[i]+" "+line2[i]+"\n")list.append(a)line=f1.readlines()
with open('zhongliang/hebing.txt', 'a') as month_file: for line in list:s = linemonth_file.writelines(s)
# coding=gbk
import numpy as np
import xlrd
import xlwt
f = open('zhongliang/hebing.txt','r') #打开数据文本文档,注意编码格式的影响,这里用的是ANSI编码
wb = xlwt.Workbook(encoding = 'ANSI') #打开一个excel文件
ws1 = wb.add_sheet('first') #添加一个新表
row = 1 #写入的起始行
col = 0 #写入的起始列
k = 0
ws1.write(0, 0 ,"lunkuo")
ws1.write(0, 1 ,"zhongliang")
for lines in f: a = lines.split(' ') #txt文件中每行的内容按‘ ’分割并存入数组中k+=1#rb = xlrd.open_workbook('C:\\Users\\DELL\\Desktop\\biao.xlsx') #ws1 = rb.get_ws1(0)for i in range(len(a)):ws1.write(row, col ,a[i])#向Excel文件中写入每一项col += 1row += 1col = 0
wb.save("zhongliang/hebing.xlsx")
7.1 以下为最小二乘法回归
# import pandas as pd
# data = pd.read_excel("zhongliang/hebing.xlsx")
# data
# import matplotlib.pyplot as plt
# data = pd.read_excel("zhongliang/hebing.xlsx")
# data.plot.scatter(x= 'lunkuo',y='zhongliang')
# plt.show()
# from sklearn.linear_model import LinearRegression
# features = data ['lunkuo'].values.reshape(-1,1)
# target = data ['zhongliang']
# regression = LinearRegression()
# model = regression.fit(features,target)
# model.intercept_
# #b值
# model.coef_
# #K值
# import matplotlib.pyplot as plt
# data = pd.read_excel("zhongliang/hebing.xlsx")
# data.plot.scatter(x= 'lunkuo',y='zhongliang')
# plt.plot([0,1000],[0,10.97144892],'r--' )
# plt.show()
# new_x = 1000
# new_x = np.array(new_x).reshape(1, -1)
# pre_y = model.predict(new_x)
# print(pre_y)
pip install measure
pip install imutils
最小二乘法拟合获取的轮廓数据以及拟合线条图
7.2 搭建重量模型
首先载入需要用到的库,它们分别是:
paddle.fluid:引入PaddlePaddle深度学习框架的fluid版本库;
numpy:NumPy是Python语言的一个扩展程序库。支持高端大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。NumPy的核心功能是"ndarray"(即n-dimensional array,多维数组)数据结构。
os: python的模块,可使用该模块对操作系统、目录、文件等进行操作
matplotlib.pyplot:用于生成图,在验证模型准确率和展示成本变化趋势时会使用到
#1,导入各类库
import paddle
import paddle.fluid as fluid
from paddle.fluid.dygraph.nn import Linear
import numpy as np
import random
# 载入数据
data = np.genfromtxt("zhongliang/hebing_train.csv", delimiter=",",encoding='gb2312')
x_data = data[1:,0]
y_data = data[1:,1]
#把列表转为数组,重构数组
x_data=np.array(x_data).reshape([-1,1])
y_data=np.reshape(y_data,[-1,1])
x_data=np.array(x_data).astype("float32")
y_data=np.array(y_data).astype("float32")
#3,准备模型
class MNIST(fluid.dygraph.Layer):def __init__(self):super(MNIST,self).__init__()# 定义一个全连接层,输入输出1self.fc=Linear(input_dim=1,output_dim=1,act=None)def forward(self,inputs):#网络向前方式x=self.fc(inputs)return x
#4,开始训练
with fluid.dygraph.guard():model=MNIST()model.train()iterid=[] #训练次数列表losses=[] # 损失值列表#将numpy.ndarray转换为Tensorimage=fluid.dygraph.to_variable(x_data)label=fluid.dygraph.to_variable(y_data)# 定义优化器,使用梯度下降Adam优化器,学习率设置为0.001optimizer = fluid.optimizer.AdamOptimizer(learning_rate=0.001, parameter_list=model.parameters())#optimizer = fluid.optimizer.SGDOptimizer(learning_rate=0.001, parameter_list=model.parameters())#optimizer = fluid.optimizer.AdamOptimizer(learning_rate=0.01, regularization=fluid.regularizer.L2Decay(regularization_coeff=0.1),# parameter_list=model.parameters())EPOCH_NUM=30000 #训练次数for epoch_id in range(EPOCH_NUM):#计算模型输出predict=model(image)#PaddlePaddle提供了很多的损失函数的接口,比如交叉熵损失函数(cross_entropy)。
#因为本项目是一个线性回归任务,所以我们使用的是均方差损失函数。
#可以调用fluid.layers.square_error_cost(input= ,laybel= )实现方差计算。
#因为fluid.layers.square_error_cost(input= ,laybel= )求的是一个Batch的损失值,
#所以我们还要通过调用fluid.layers.mean(loss)对方差求平均。
#将输入定义为 房价预测值,label定义为 标签数据。进而计算损失值。loss=fluid.layers.square_error_cost(predict,label)#计算损失函数avg_loss=fluid.layers.mean(loss)iterid.append(epoch_id)losses.append(avg_loss.numpy())# 保存损失值中间状态if epoch_id % 1000 ==0:print("epoch_id is {},avg_loss is {}".format(epoch_id,avg_loss.numpy()))avg_loss.backward()#反向传播 得到参数的梯度参数值optimizer.minimize(avg_loss)# 最小化损失函数,清除本次训练的梯度model.clear_gradients#保存模型参数fluid.save_dygraph(model.state_dict(),"one_yuan")
#输出模型的损失图
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(iterid,losses)
plt.grid()
plt.show()
#5,检测效果
Input = 29300with fluid.dygraph.guard():model_dict,_=fluid.load_dygraph("one_yuan")model.load_dict(model_dict)#加载模型参数model.eval()#29300来测试,正确结果为3.335test_data=np.array([Input]).astype("float32")test_data=fluid.dygraph.to_variable(test_data)result=model(test_data)print(result.numpy())
model.parameters()
#############验证处from PIL import Image
import PIL.ImageOps
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from skimage.io import imsave
from PIL import ImageEnhance
import cv2with open("data/test_list.txt","r") as f:filepath = f.readlines()data =[filepath[i].split(" ")[0] for i in range(10)]#背景转化为黑色
#in_path = "data/fish_pic/fish_data/fish_image23/fish_3/300.jpg"
xuhao = 4 #这里为需要计算的图片质量序号,(0——9)
in_path = data[xuhao]
print('path is : '+data[xuhao])
dizhi="zhongliang/1.jpg"
out_path = dizhi
out_path_area = "zhongliang/2.jpg"
Img = cv2.imread(str(in_path))
Img2 = np.array(Img, copy=True)
# 1.全局阈值法
# ret, mask_all = cv2.threshold(src=Img, # 要二值化的图片
# thresh=200, # 全局阈值
# maxval=255, # 大于全局阈值后设定的值
# type=cv2.THRESH_BINARY) # 设定的二值化类型,THRESH_BINARY:表示小于阈值置0,大于阈值置填充色# imsave(out_path, mask_all)
white_px = np.asarray([255, 255, 255])
black_px = np.asarray([0 , 0 , 0 ])(row, col, _) = Img.shapefor a in range(row-2):for b in range(col-2):da = 0r = a+1c =b+1#像素点周边八个区域,内部点计算算法px = Img[r][c]p1 = Img[r-1][c-1], p2 = Img[r-1][c] ,p3 = Img[r-1][c+1] ,p4 = Img[r][c-1] ,p5 = Img[r][c+1] ,p6 = Img[r+1][c-1],p7 = Img[r+1][c] ,p8 = Img[r+1][c+1] if all(px == white_px):Img2[r][c] = black_pximsave(out_path, Img2)#对转化后的图片进行描边
mat_img = cv2.imread(out_path)
mat_img2 = cv2.imread(out_path,cv2.CV_8UC1)#cv2.imshow("Initial image",mat_img)
#cv2.waitKey(0)#自适应分割+提取轮廓+标记轮廓
dst = cv2.adaptiveThreshold(mat_img2,210,cv2.BORDER_REPLICATE,cv2.THRESH_BINARY_INV,3,10)
contours,heridency = cv2.findContours(dst,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(mat_img,contours,-1,(255,0,255),3)imsave(out_path_area, mat_img)
#计算轮廓面积
area = 0def MY_ConTourArea(cnt): #传入一个轮廓rect = cv2.minAreaRect(cnt) #最小外接矩形box = cv2.boxPoints(rect)box = np.int0(box)return cv2.contourArea(box)#cv2.contourArea()底层使用的是格林公式,对边界上的所有像素点没有相加for i in contours:area += MY_ConTourArea(i)
print("area is :",area)areatwo = 0
for i in contours:areatwo += cv2.contourArea(i)
areatwo*=100
print("areatwo is :",areatwo)#计算确切面积
#获取系数
Note=open('data/jisuan.txt',mode='r')
notedata = Note.readlines()
xishu = 0
datab = 0
fishmapdata = open('zhongliang/fish_data_map.txt',mode='r')
for line in fishmapdata:if int(line[0:2])==int(notedata[xuhao]): #这里的序号指的是需要计算的图片的在“jisuan.txt”文件中的序号,然后通过这个对应的序号在map中找到相对的质量系数#print('the fishmapdata is : '+line[2:10])xishu = line[2:14]datab = line[14:25]print('the mapdata is : '+ str(notedata[xuhao])+'the fishmapdata is : '+str(xishu))
print('the datab is : '+str(datab))#将预测结果保存起来
# Note = open('zhongliang/picture_one/yuce.txt',mode='a')
# Note.write("The path is: "+str(in_path)+" ") #写数据#根据最小二乘法得到回归方程的k和b后,进行y=Kx+b的模型计算计算lastdata = areatwo*float(xishu)+float(datab)
last = "The weight of this fish is : "+str(lastdata)+" kg"
# Note.write(str(lastdata))
# Note.write("\n")
print(last)plt.figure(dpi=150)
test_img = in_path #提取路径
img = Image.open(test_img).resize((256,256))
img=ImageEnhance.Contrast(img).enhance(5)
plt.title(last)
plt.imshow(Img2)# import imutils
# cnts = cv2.findContours(dst, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# cnts = imutils.grab_contours(cnts)
# c = max(cnts, key = cv2.contourArea)
# print("area is :",c)# #计算确切面积
# Note=open('data/jisuan.txt',mode='r')
# notedata = Note.readlines()
# xishu = 0
# datab = 0
# fishmapdata = open('zhongliang/fish_data_map.txt',mode='r')
# for line in fishmapdata:
# if int(line[0:2])==int(notedata[xuhao]): #这里的序号指的是需要计算的图片的在“jisuan.txt”文件中的序号,然后通过这个对应的序号在map中找到相对的质量系数
# #print('the fishmapdata is : '+line[2:10])
# xishu = line[2:13]
# datab = line[13:40]# print('the mapdata is : '+ str(notedata[xuhao])+'the fishmapdata is : '+str(xishu))
# print('the datab is : '+str(datab))# #根据最小二乘法得到回归方程的k和b后,进行y=Kx+b的模型计算计算# lastdata = area*float(xishu)+float(datab)
# last = "The weight of this fish is : "+str(lastdata)+" kg"
# print(last)# plt.figure(dpi=150)
# test_img = in_path #提取路径
# img = Image.open(test_img).resize((256,256))
# img=ImageEnhance.Contrast(img).enhance(5)
# plt.title(last)
# plt.imshow(img)#################################################################################
# 在二值图像中,如果两个像素点相邻且值相同(同为0或同为1),那么就认为这两个像素点在一个相互连通的区域内。
# 而同一个连通区域的所有像素点,都用同一个数值来进行标记,这个过程就叫连通区域标记。
# 通过标记所有的联通区域的方式确定图片中淡水鱼的轮廓面积(筛选出大于500像素点的轮廓并做记录,最大的一块为淡水鱼轮廓面积)# #coding=utf-8
# import numpy as np
# import scipy.ndimage as ndi
# from skimage import measure,color
# import matplotlib.pyplot as plt# # data = microstructure(l=256)*1 #生成测试图片
# in_path = "data/fish_pic/fish_data/fish_image23/fish_3/300.jpg"
# Img = cv2.imread(str(in_path))
# labels = measure.label(in_path,connectivity=2) ## #筛选连通区域大于500的
# properties = measure.regionprops(labels)# valid_label = set()
# for prop in properties:
# if prop.area > 500:
# valid_label.add(prop.label)
# current_bw = np.in1d(labels, list(valid_label)).reshape(labels.shape)# dst = color.label2rgb(current_bw) #根据不同的标记显示不同的颜色
# print('regions number:', current_bw.max()+1) #显示连通区域块数(从0开始标记)# fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(8, 4))
# ax1.imshow(data, plt.cm.gray, interpolation='nearest')
# ax1.axis('off')
# ax2.imshow(current_bw, plt.cm.gray, interpolation='nearest')
# ax2.axis('off')
# ax3.imshow(dst,interpolation='nearest')
# ax3.axis('off')# fig.tight_layout()
# plt.show()
import numpy as np
import matplotlib.pyplot as plt
import math
file1 = open('zhongliang/picture_one/picture_one_yuce.txt') #打开文档
file2 = open('zhongliang/picture_one/picture_one_zhenshi.txt') #打开文档
data1 = file1.readlines() #读取文档数据
data2 = file2.readlines() #读取文档数据
part_1 = [] #新建列表,用于保存第一列数据
part_2 = []
for num in data1:# split用于将每一行数据用逗号分割成多个对象#取分割后的第0列,转换成float格式后添加到para_1列表中part_1.append(float(num.split(',')[0]))
for num in data2:# split用于将每一行数据用逗号分割成多个对象#取分割后的第0列,转换成float格式后添加到para_1列表中part_2.append(float(num.split(',')[0]))
plt.figure()
plt.title("Contrast")
plt.xlabel("Sign")
plt.ylabel("Weight")
plt.plot(part_1,color = 'green', label = 'yuce')
plt.plot(part_2,color = 'red', label = 'zhenshi')
plt.show()
#1、平均绝对误差(Mean Absolute Error, MAE):是绝对误差的平均值,可以更好地反映预测值误差的实际情况
#方法一:
Sum = 0
for i in range(len(part_1)):Sum += abs(part_2[i] - part_1[i])MAE = Sum/len(part_1)print("Mean absolute error : " + str(MAE))#方法二:
# from sklearn.metrics import mean_absolute_error
# print(mean_absolute_error(part_1,part_2))#Y_real为实际值,Y_pre为预测值
#2、均方误差(Mean Square Error, MSE):是真实值与预测值的差值的平方,然后求和的平均,一般用来检测模型的预测值和真实值之间的偏差
MSE =np.sum([(x - y) ** 2 for x, y in zip(part_1, part_2)]) / len(part_1)
print("The accuracy of the regression model is measured by mean square error :" + str(MSE))#3、均方根误差(Root Mean Square Error, RMSE):即均方误差开根号,方均根偏移代表预测的值和观察到的值之差的样本标准差
RMSE = math.sqrt(MSE)
print("The root mean square error measures the accuracy of regression models, :" + str(RMSE))
#4、R²(R squared, Coefficient of determination):决定系数,反映的是模型拟合数据的准确程度,一般R² 的范围是0到1。
#其值越接近1,表明方程的变量对y的解释能力越强,这个模型对数据拟合的也较好
#计算R²
from sklearn.metrics import r2_score
print(r2_score(part_2,part_1))#Y_real为实际值,Y_pre为预测值
import matplotlib.pyplot as plt
y = np.linspace(0,10,100)
file1 = open('zhongliang/picture_two/picture_two_yuce.txt') #打开文档
file2 = open('zhongliang/picture_two/picture_two_zhenshi.txt') #打开文档
file3 = open('zhongliang/picture_two/picture_two_lunkuo.txt') #打开文档
data1 = file1.readlines() #读取文档数据
data2 = file2.readlines() #读取文档数据
data3 = file3.readlines() #读取文档数据part_1 = [] #新建列表,用于保存第一列数据
part_2 = []
part_3 = []
for num in data1:# split用于将每一行数据用逗号分割成多个对象#取分割后的第0列,转换成float格式后添加到para_1列表中part_1.append(float(num.split(',')[0]))
for num in data2:# split用于将每一行数据用逗号分割成多个对象#取分割后的第0列,转换成float格式后添加到para_1列表中part_2.append(float(num.split(',')[0]))
for num in data3:# split用于将每一行数据用逗号分割成多个对象#取分割后的第0列,转换成float格式后添加到para_1列表中part_3.append(float(num.split(',')[0]))plt.figure()
plt.title("Contrast——Weight")
plt.xlabel("Contour area")
plt.ylabel("Weight")
plt.plot(part_3,part_1,color = 'green', label = 'yuce')
plt.plot(part_3,part_2,color = 'red', label = 'zhenshi')
plt.show()
回归模型的准确率是只预测值与真实值之间的平均差异。通常采用均方误差(Mean Squared Error,MSE)或者均方根误差(Root Mean Squared Error,RMSE)来度量回归模型的准确率,MSE表示预测值与真实值之间的平方差的平均值,计算公式为:MSE=(1/n)*∑(yi-yi估计)²,其中yi为预测值,n为样本数,RMSE为MSE的平方根。
实验结果分析
1.淡水鱼单个体识别效果
2.使用残差网络单次识别多只鲈鱼结果
3.获取轮廓面积算法选择算法一,算法二淡水鱼类的形态与其轮廓的最小外接矩形有很大的偏差,舍去。
4.算法三最大连通区域中由于背景经过黑户,最终得到的效果为背景中的某一块区域,不符合结果。
5.体重模型损失函数结果
6.所有损失函数值折线图
7.实验个体原图及计算出的体重图
8.五十只鲈鱼个体体重预测数据(绿色折线)和真实数据(红色折线),拟合效果较好。横坐标为鲈鱼个体编号,纵坐标为质量。
9.五十只鲈鱼个体体重预测情况(绿色是预测值,红色为真实值),横坐标为轮廓面积,纵坐标为质量。
算出来的轮廓面积与质量映射数据集中,含有一部分噪声点异常点,有一些噪声点的偏差与普通数据相比差距异常大,通过去除这些噪声点异常点后再投入拟合模型训练,之后再使用模型预测在实际应用中会更好。
相关文章:

基于深度学习淡水鱼体重智能识别模型研究
工作原理为:首先对大众淡水鱼图片进行数据清洗并做标签分类,之后基于残差网络ResNet50模型进行有监督的分类识别训练,获取识别模型。其次通过搭建回归模型设计出体重模型,对每一类淡水鱼分别拟合出对应的回归方程,将获…...

Nginx专题(1)--linux安装nginx
ngixn安装 安装依赖包 yum install gcc yum install pcre-devel yum install zlib zlib-devel yum install openssl openssl-devel 安装nginx 下载nginx的tar包 登录http://nginx.org/en/download.html,下载nginx的Stable version版本,并解压 #执行c…...

系统集成中级计算汇总
基本计算: EV 挣值 (实际完成的工作量) AC 实际发生的花费 PV 计划花费(预算) CV 成本 SV 进度 CV 和 SV 的计算 都是通过EV 减去另一个值 CV EV-AC SV EV-PV 成本 chengben C 开头 所以CV 是成本 CV 中有个C 所以用到的是 AC ,另外一个则是剩余的PV CV SV 计算…...

json.stringify的高级用法,和for of的原理
** /* for of 是用来循环可迭代属性的,如何判断是否是可迭代属性,数据原型链上有个Symbol.iterator说明这个数据是可迭代数据 Symbol.iterator是一个函数,调用此函数,会返回一个对象,对象的内部有一个next函数,调用next函数会返回一个对象这个对象内部有value和done值…...

SpringCloudAlibaba微服务实战系列(三)Sentinel1.8.0+流控
SpringCloudAlibaba–Sentinel Sentinel被称为分布式系统的流量防卫兵,是阿里开源流量框架,从服务限流、降级、熔断等多个纬度保护服务。Sentinel同时提供了简洁易用的控制台,可以看到接入应用的秒级数据,并可以在控制台设置一些…...

mybatis - no getter for property,以及@JsonIgnore
There is no getter for property named user_full_name in class com.book.erp.entity.user.QueryUser Mybatis 配置错误,XML配置文件有Java对象以及数据库字段,配置时需要小心 user_full_name是数据库字段,不需要有get 和 set方法…...

云原生周刊:K8s v1.28 中的结构化身份验证配置
开源项目推荐 KubeLinter KubeLinter 是一种静态分析工具,用于检查 Kubernetes YAML 文件和 Helm 图表,以确保其中表示的应用程序遵循最佳实践。 DB Operator DB Operator 减轻了为 Kubernetes 中运行的应用程序管理 PostgreSQL 和 MySQL 实例的痛苦…...

支持向量机概述
支持向量机在深度学习技术出现之前,使用高斯核的支持向量机在很多分类问题上取得了很好的结果,支持向量机不仅用于分类,还可以用于回归问题。它具有泛化性能好,适合小样本和高维特征的优点。 1. SVM引入 1.1支持向量机分类 支持向量机的基本模型是定义在特征空间上的间隔…...

安装x265
一、编译libx265源码 libx265是用CMAKE编译的,故先下cmake,我是centos系统,命令: yum install cmake -y进入目录./x265_1.9/build/linux/下,执行脚本: sh make-Makefiles.bash选择好之后,输入…...

设计模式-观察者模式
一.观察者模式 观察者模式是一种行为型设计模式,它定义了一种一对多的依赖关系,当一个对象的状态发生改变时,其所有依赖者都会收到通知并自动更新。当对象间存在一对多关系时,则使用观察者模式(Observer Pattern&…...

K8s使用Ceph作为后端存储
Ceph概述 部署Ceph集群 Ceph存储使用 Pod使用Ceph持久化数据 Ceph监控 Rook部署Ceph 1❖ Ceph概述 Ceph介绍 Ceph架构 Ceph核心概念 Ceph介绍 Ceph是一个开源的分布式存储系统,具有高扩展性、高性能、高可靠性等特点,提 供良好的性能、可靠性和可扩展…...

hive整合es,详细过程。
参考官网 Apache Hive integration | Elasticsearch for Apache Hadoop [7.17] | Elastic 官网的介绍很简单,我看了很多博客,写的也很简单,但是我搞了半天才勉强成功,分享下,免得各位多走弯路。 环境准备 官网也很…...

vue中tab隐藏display:none(v-show无效,v-if有效)
目录 背景 原因:display: table-cell>display:none 解决: 方法A.获取元素设置display(适用于 简单场景) 方法B.自定义tabs (适用于 复杂场景) 背景 内联样式(style“ ”) /this.$…...

2023年进阶测试,从接口测试到接口自动化测试总结,一篇彻底打通...
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 json模块的使用 …...

客户支持工具从被动到主动的演变
在当日新月异的商业环境中,企业需要适应不断增长的客户需求,优质的客户支持变得越来越重要。客户支持工具从传统系统到尖端 AI驱动解决方案的演变具有变革性,增强了主动和无缝的支持体验。所以,使用正确的客户服务工具很重要&…...

网络安全行业相关证书
一:前言 对于考证这个话题,笔者的意见是:“有比没有好,有一定更好,但不一定必须;纸上证明终觉浅,安全还得实力行”。很多人对于各种机构的考证宣传搞得是云里雾里,不知道网络安全行业…...

[内网渗透]SUID提权
文章目录 [内网渗透]SUID提权0x01.什么是SUID?0x02.如何设置SUID?0x03.查找属主为root的SUID文件0x04.进行SUID提权1.find提权2.vim/vi/vim.tiny 以root权限修改文件3.bash提权4.less/more执行系统命令5.nano以root权限修改文件6.awk执行系统命令7.cp以r…...

clang 编译器前端 分析
clang 编译器前端 分析 clang的python接口教程(二) Python接口clang解析C语言AST抽象语法树 clang static analyzer源码分析 clang静态代码分析是clang相对于gcc一个比较能够引起关注的点,特别是clang静态代码分析基于checker的架构和大部…...

3个月精通Python(基础篇)——第1天:Python和Vscode环境安装
安装 Python: 访问 Python 官网 下载 ,下载最新的 Python 安装程序。 双击安装程序,按照提示进行安装设置即可。 在安装过程中,请勾选“Add Python X.X to PATH”选项,这样安装后 Python 会被自动添加到系统的环境变量…...

react native web RN webpack nginx 部署
# nginx配置 location /app {root html;index index.html;# url 切换时始终返回index.htmltry_files $uri /app/index.html; } # 图片样式缓存1年 location ~* /app.*\.(js|css|png|jpg)$ {access_log off;expires 365d; } # html/xml/json 文件不缓存 location ~* /app.…...

Jmeter性能测试之Beanshell解析并提取json响应
1:前置条件 将fastjson-1.2.49.jar包置于jmeter的lib目录下,并将该jar包添加到测试计划的Library中;否则会报:Typed variable declaration : Class: JSONObject not found in namespace的错误 2:解析思路 利用beansh…...

vue-echarts配置项详解
起因 最近接手了一个vue3项目,echarts用的是"vue-echarts": “^6.0.0”,每次查看文档的时候痛苦不已,找一个配置要花费大量时间,所以这篇文章,主要就是为了记录比较常见的一些配置。 主要会写三种图的配置…...

两个csv进行根据相同字段进行合并
源文件,第一列,编号0 目标文件, 编号3 根据社区名称进行匹配,然后将第一个csv文件的经纬度添加到第二个文件中。 import csvsource r"D:\000datasets\链家房价数据\2020去重后社区名称地理编码.csv" target r"…...

SolidWorks绘制Maxwell仿真用带桥接的三维平板螺旋线圈
文章目录 前言一、建立涡状线二、拉伸方法1(建立工作面,较复杂)三、拉伸方法2(穿透,较简单)四、建立桥接 前言 在使用Maxwell进行电磁场仿真时,经常需要绘制各种异形线圈,由于Maxwel…...

【每日一个知识点二】原型链
我都是想到啥写啥,丝毫没有规律。前面聊到箭头函数没有原型,就想到了再整理一篇原型链的。 原型 原型是JavaScript中对象的一个属性,它指向另一个对象,用于实现继承关系。每个对象都有一个原型属性__proto__,它指向它…...

placeholder样式自定义(uniapp 微信小程序、h5)
一、使用uniapp开发 ①第一种方式:(写在行内) <input type"text" placeholder"姓名" placeholder-style"font-size:28rpx;color:#999999;" />②第二种方式: (给input加上placeho…...

【LeetCode】383. 赎金信
题目:383. 赎金信 由于此题只含有小写字母,并且magazine里面的字母不可重复使用. 故首先用一个长度为26的整形数组记录magazine里字母出现的次数。 再用这个整形数组跟ransomeNote进行遍历比较,当数组中出现-1时,说明false,否则true. 代码&am…...

【算力革命】算力架构
AI芯片可按架构分为CPU、GPU、FPGA、ASIC,各架构的优缺点可参考以下文章: CPU、GPU、FPGA、ASIC等AI芯片特性及对比_cpu gpu fpga_maopig的博客-CSDN博客 最近,新名词 DSA(Domain Specific Architecture,特定领域架构…...

【视觉SLAM入门】4.3. (非线性最小二乘问题)优化算法实现-ceres和g2o, 图优化理论
"天道不争而善胜" 1. Ceres库1.1 名词解释1.2 具体例子1.3 C实现1. 定义代价函数2. 构建最小二乘问题3. 配置求解器,开始优化4. 优化完毕,查看结果 2. G2O(General Graphic Optimization)2.1 图优化2.2 具体例子2.3 C实现1. 定义顶点2. 定义边…...

vue Can‘t resolve ‘path‘
BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default. This is no longer the case. Verify if you need this module and configure a polyfill for it. 这句话的意思是webpack 5之前是自动导入node一些核心模块的垫片…...