同步操作将从 dromara/EasyAi 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
本包说明:
链接:https://pan.baidu.com/s/1Vzwn3iMPBI-FAXBDrCSglg
密码:7juj
入手门槛低,简单配置,快速上手
训练过程
Picture picture = new Picture();//图片解析类
Config config = new Config();//配置文件
config.setTypeNub(2);//设置训练种类数
config.setBoxSize(125);//设置物体大致大小 单位像素 即 125*125 的矩形
config.setPictureNumber(5);//设置每个种类训练图片数量 某个类别有几张照片,注意所有种类照片数量要保持一致
config.setPth(0.7);//设置可信概率,只有超过可信概率阈值,得出的结果才是可信的 数值为0-1之间
config.setShowLog(true);//输出学习时打印数据
Distinguish distinguish = new Distinguish(config);//创建识别类
distinguish.setBackGround(picture.getThreeMatrix("E:\\ls\\fp15\\back.jpg"));//设置识别的背景图片(该api为固定背景)
List<FoodPicture> foodPictures = new ArrayList<>();//创建训练模板集合
for (int i = 1; i < 3; i++) {
FoodPicture foodPicture = new FoodPicture();//创建每一类图片的训练模板类
foodPictures.add(foodPicture);//将该类模板加入集合
List<PicturePosition> picturePositionList = new ArrayList<>();//创建该类模板的训练集合类
foodPicture.setId(i + 1);//设置该图片类别id
foodPicture.setPicturePositionList(picturePositionList);
for (int j = 1; j < 6; j++) {//训练图片数量为 每种五张 注意跟config 中的 pictureNumber 要一致
String name;
if (i == 1) {//加载图片url地址名称
name = "a";
} else {
name = "b";
}
PicturePosition picturePosition = new PicturePosition();
picturePosition.setUrl("E:\\ls\\fp15\\" + name + i + ".jpg");//加载该类别图片地址
picturePosition.setNeedCut(false);//是否需要剪切,若训练素材为充满全图图片,则充满全图不需要剪切 写false
picturePositionList.add(picturePosition);//加载
}
}
distinguish.studyImage(foodPictures);//进行学习
System.out.println(JSON.toJSONString(distinguish.getModel()));//输出模型保存,将模型实体类序列化为json保存
///////////////////////////////////////////////////////////////////////
初始化过程
Picture picture = new Picture();//图片解析类
Config config = new Config();//配置文件
config.setTypeNub(2);//设置类别数量
config.setBoxSize(125);//设置物体大小 单位像素
config.setPictureNumber(5);//设置每个种类训练图片数量
config.setPth(0.7);//设置可信概率,只有超过可信概率阈值,得出的结果才是可信的
config.setShowLog(true);//输出学习时打印数据
Distinguish distinguish = new Distinguish(config);//识别类
distinguish.insertModel(JSONObject.parseObject(ModelData.DATA, Model.class));//将之前训练时保存的训练模型反序列化为实体类后,注入模型
完成后请单例Distinguish类,即完成系统启动时初始化过程
///////////////////////////////////////////////////////////////////////
识别过程
Distinguish distinguish; 此识别类为系统启动时已经初始化的 单例distinguish,识别过程请不要 "new" 这个类
for (int i = 1; i < 8; i++) {
System.out.println("i====" + i);
ThreeChannelMatrix t = picture.getThreeMatrix("E:\\ls\\fp15\\t" + i + ".jpg");//将识别图片转化为矩阵
Map<Integer, Double> map = distinguish.distinguish(t);//识别结果
for (Map.Entry<Integer, Double> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":" + entry.getValue());//识别结果打印
}
}
////////////////////////////////////////////////////////////////////////////////////
识别结果打印说明(此为本包提供的测试图片样本的 输出结果说明,在之前的训练中橘子设置的id为2,苹果为3)
i====1//第一张图 结果为 橘子,出现2:代表类别。:0.8874306751020916,带表该类别权重,权重越高说明该类别的物品在当前 图片中数量越多或者面积越大。
2:0.8874306751020916 说明(图1有橘子,权重为:0.8874306751020916)
i====2
2:0.8878192183606407
i====3
3:0.7233916245920673说明(图3有苹果,权重为:0.7233916245920673)
i====4
2:0.9335699571468958说明(图4有橘子,权重为:0.9335699571468958)
3:0.7750825597199661说明(图4有苹果,权重为:0.7750825597199661)
i====5
3:0.8481590575557582
i====6
2:0.7971025523095067
i====7
2:1.5584968376080388(图7有橘子,权重为:1.5584968376080388)
3:0.8754957897385587(图7有苹果,权重为:0.8754957897385587)
本演示样例代码位置在: src/test/java/org/wlld/ImageTest.java
本演示训练素材位置在: src/test/image
注意:以上图片识别代码样例为训练素材为物品全图充满图片(自己看能看到橘子训练图片为全图充满,苹果也是).自行开发时用以上代码样例时,请也使用全图充满训练物品的图片来做训练,非全图充满训练素材图训练api有变化!
//创建模板读取类
TemplateReader templateReader = new TemplateReader();
//读取语言模版,第一个参数是模版地址,第二个参数是文本编码方式
//同时也是学习过程
templateReader.read("/Users/lidapeng/Desktop/myDocment/a1.txt", "UTF-8");
//学习结束获取模型参数
//WordModel wordModel = WordTemple.get().getModel();
//不用学习注入模型参数
//WordTemple.get().insertModel(wordModel);
Talk talk = new Talk();
//输入语句进行识别,若有标点符号会形成LIST中的每个元素
//返回的集合中每个值代表了输入语句,每个标点符号前语句的分类
List<Integer> list = talk.talk("帮我配把锁");
System.out.println(list);
//这里做一个特别说明,语义分类的分类id不要使用"0",本框架约定如果类别返回数字0,则意味不能理解该语义,即分类失败
//通常原因是模板量不足,或者用户说的话的语义,不在你的语义分类训练范围内
//创建一个DNN神经网络管理器
NerveManager nerveManager = new NerveManager(...);
//构造参数
//sensoryNerveNub 感知神经元数量 即输入特征数量
//hiddenNerverNub 每一层隐层神经元的数量
//outNerveNub 输出神经元数量 即分类的类别
//hiddenDepth 隐层神经元深度,即学习深度
//activeFunction 激活函数
//isDynamic 是否启用动态神经元数量(没有特殊需求建议为静态,动态需要专业知识)
public NerveManager(int sensoryNerveNub, int hiddenNerverNub, int outNerveNub, int hiddenDepth, ActiveFunction activeFunction, boolean isDynamic)
nerveManager.getSensoryNerves()获取感知神经元集合
//eventId:事件ID
//parameter:输入特征值
//isStudy:是否是学习
//E:特征标注
//OutBack 回调类
SensoryNerv.postMessage(long eventId, double parameter, boolean isStudy, Map<Integer, Double> E, OutBack outBack)
//每一次输出结果都会返回给回调类,通过回调类拿取输出结果,并通过eventId来对应事件
//创建一个内存中的数据表
DataTable dataTable = new DataTable(column);
//构造参数是列名集合
public DataTable(Set<String> key)
//指定主列名集合中该表的主键
dataTable.setKey("point");
//创建一片随机森林
RandomForest randomForest = new RandomForest(7);
//构造参数为森林里的树木数量
public RandomForest(int treeNub)
//唤醒随机森林里的树木
randomForest.init(dataTable);
//将加入数据的实体类一条条插入森林中
randomForest.insert(Object object);
//森林进行学习
randomForest.study();
//插入特征数据,森林对该数据的最终分类结果进行判断
randomForest.forest(Object objcet);
TempleConfig templeConfig = new TempleConfig(false, true);
使用TempleConfig()有参构造,第一个参数目前依然固定传false(因为有功能还没完成),第二个参数是一个布尔值是否忽略精度。
众所周知JAVA计算浮点是有精度损失的,如果选择true则使用大数计算类即无精度损失(默认为FALSE),但是这是以速度变慢十倍以上为代价的。
忽略精度和使用精度准确度上差距,平均在5-6个百分点之间,所以用户按照自己的需求来判断是否使用精度计算。优点:准确度提升5-6个百分点,配合DNN分类器可达99%以上的准确率
缺点:运算速度变慢十倍以上,从百毫秒变为一至两秒
TempleConfig templeConfig = new TempleConfig(false, true);
templeConfig.setClassifier(Classifier.DNN);
在TempleConfig类调用init()方法前选择使用的分类器setClassifier()
public class Classifier {//分类器
public static final int LVQ = 1;//LVQ分类
public static final int DNN = 2; //使用DNN分类
public static final int VAvg = 3;//使用特征向量均值分类
}
目前easyAi提供三种分类器,即用户选择一种参数设置进配置模板类
这三种分类器的特点
- LVQ:若用户训练图片量较少,比如一个种类只有一两百张图片,则使用此分类器达到当前条件下最大识别成功率
- VAvg:若用户训练图片较少,同时分类数量也很少,比如只训练两三种物体识别,则VAvg达到当前最大识别成功率
- DNN:若用户训练图片较多,每种分类1500张训练图片,则使用此分类器,准确率98%+。
- 若不设置分类器,则框架默认使用VAvg分类器
使用DNN的话,API略有区别
//创建图片解析类
Picture picture = new Picture();
//创建一个静态单例配置模板
static TempleConfig templeConfig = new TempleConfig();
//使用DNN分类器
templeConfig.setClassifier(Classifier.DNN);
//第三个参数和第四个参数分别是训练图片的宽和高,为保证训练的稳定性请保证训练图片大小的一致性
templeConfig.init(StudyPattern.Accuracy_Pattern, true, 640, 640, 2);
//将配置模板类作为构造塞入计算类
Operation operation = new Operation(templeConfig);
//一阶段 循环读取不同的图片
for (int i = 1; i < 1900; i++) {
//读取本地URL地址图片,并转化成矩阵
Matrix a = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/a" + i + ".jpg");
Matrix c = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/c" + i + ".jpg");
//矩阵塞入运算类进行学习,第一个参数是图片矩阵,第二个参数是图片分类标注ID,第三个参数是第一次学习固定false
operation.learning(a, 1, false);
operation.learning(c, 2, false);
}
for (int i = 1; i < 1900; i++) {
Matrix a = picture.getImageMatrixByLocal("D:\\share\\picture/a" + i + ".jpg");
Matrix c = picture.getImageMatrixByLocal("D:\\share\\picture/c" + i + ".jpg");
operation.normalization(a, templeConfig.getConvolutionNerveManager());
operation.normalization(c, templeConfig.getConvolutionNerveManager());
}
templeConfig.getNormalization().avg();
for (int i = 1; i < 1900; i++) {
//读取本地URL地址图片,并转化成矩阵
Matrix a = picture.getImageMatrixByLocal("D:\\share\\picture/a" + i + ".jpg");
Matrix c = picture.getImageMatrixByLocal("D:\\share\\picture/c" + i + ".jpg");
//将图像矩阵和标注加入进行学习,Accuracy_Pattern 模式 进行第二次学习
//第二次学习的时候,第三个参数必须是 true
operation.learning(a, 1, true);
operation.learning(c, 2, true);
}
大家可以看到如果使用DNN,在一阶段学习和二阶段学习之间多了一段代码即:
for (int i = 1; i < 1900; i++) {
Matrix a = picture.getImageMatrixByLocal("D:\\share\\picture/a" + i + ".jpg");
Matrix c = picture.getImageMatrixByLocal("D:\\share\\picture/c" + i + ".jpg");
operation.normalization(a, templeConfig.getConvolutionNerveManager());
operation.normalization(c, templeConfig.getConvolutionNerveManager());
}
templeConfig.getNormalization().avg();
templeConfig.setDeep(int deep);
若不设置默认深度为2,设置的深度越深则意味着准确率也越高,但同时也意味着你需要更多的训练图片去训练
增加一层深度,训练图片的数量至少乘以3,否则准确度不仅不会增加,反而会下降优点:更深的深度准确率可以无限接近100%,我们只要训练量足够大,我们就可以更深,越深越无敌
缺点:增加深度意味着成几何倍数提升的训练量,同时也意味着过拟合的风险
//选择分类器
templeConfig.setClassifier(Classifier.DNN);
//选择期望矩阵宽度
templeConfig.setMatrixWidth(5);
//选择正则化模式
templeConfig.setRzType(RZ.L2);
//选择DNN 深度
templeConfig.setDeep(1);
//设置学习率
templeConfig.setStudyPoint(0.05);
//设置DNN隐层宽度
templeConfig.setHiddenNerveNub(6);
//设置正则系数
templeConfig.setlParam(0.015);//0.015
templeConfig.init(StudyPattern.Accuracy_Pattern, true, width, height, 1);
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。