Sierkinhane / CRNN_Chinese_Characters_Rec

(CRNN) Chinese Characters Recognition.
1.82k stars 538 forks source link

关于训练准确率高于90%的前辈们,可否分享一下经验 #175

Closed heyhumor closed 4 years ago

heyhumor commented 4 years ago

模型测试加调整一周左右了,做的是日文半角的模型和纯数字英文的模型。测试了很久,各种调试参数,但是loss一直稳定在6~7左右,accuracy也未超过0.5,希望前辈们分享一下各自的经验,有哪些需要注意的细节。本人确实在模型设计上没什么基础,目前只能在参数上动动手脚。谢谢 2019-12-23_104106 2019-12-23_104158

shihuangxiong commented 4 years ago

我的准确率一直为0,什么情况哎?我用的他给出大的数据集

fenguoerbian commented 4 years ago

之前网络不好,没有刷出来楼主你的贴图,今天终于看到图片了。楼主你看你的结果截图里,实际上展示出来的识别细节结果那十条都是正确的吧。即使截图上显示的准确率是0.31,也不会这么巧展示出来的都识别正确了吧。 实际上你看下训练代码 crnn_main_v2.py里面的训练流程main函数和验证计算val函数就会发现,在计算准确率的时候,分母使用的是max_i * val_batchsize。而max_i是直接传递了1000进去。对于很大规模的数据集,验证集的总batch数量大于1000的情况下,这样计算的准确率是没问题的。但是对于规模较小的数据集,实际的batch数量根本就没有1000这么多,这就导致val函数算出来的准确率是不准确,而且偏小的。你可以修改一下这里的代码,在val函数中使用实际的batch数量来计算分母。

-------- 我是分割线 ------- 以我用这个repo做自己项目(文字内容与你的类似,也是符号、数字、英文)的经历来谈,主要调整过这几个方面:

  1. 字典文件,repo里面自带的字典包含了字母、数字、符号、简体、繁体,对于我的项目来说涵盖太多,做了修改。
  2. 模型读取图片时候的放缩参数(params.py里面设置),仓库原始针对的是32 * 160的白底黑字的训练集,每张图片上10个字符,测试也是将图片放缩至32像素高度。这个32目前是内部的CRNN模型写死的,但是160的像素宽度对应10个字符,这个在你自己的数据集上不一定合适(比如“战”和“占戈”,这两种字体宽度就不一样),可以调整。
  3. params.py里还有一些参数可以调整,比如对图片进行标准化时候的均值与标准差这两个参数。
  4. 你的训练集和测试集,理想状态下测试集与训练集应该服从同样的分布,这样才能期望模型在训练集上学到的东西可以很好的应用到测试集的识别上。
  5. 另外,对于一般的OCR项目,原始的训练集可能规模较小,我自己的原始训练集只有2W张左右,通过各种手段,例如人工的文字图片合成、对原始训练集进行数据增强扩充到了100W的规模
  6. 最后,改repo背后的CRNN结构。目前的CRNN是写死的,只能应用于32像素高度的图片,这是可以修改的。我自己项目里的图片由于本身质量不高,比较模糊,放缩到32像素高度更看不清楚了,就不要指望模型能学到什么有用的东西了。最后我们组还改了模型的细节,让网络适应64像素高度和96像素高度的图片。 最后通过这些方面的修改,我自己的项目里测试准确率达到99%+。
heyhumor commented 4 years ago

之前网络不好,没有刷出来楼主你的贴图,今天终于看到图片了。楼主你看你的结果截图里,实际上展示出来的识别细节结果那十条都是正确的吧。即使截图上显示的准确率是0.31,也不会这么巧展示出来的都识别正确了吧。 实际上你看下训练代码 crnn_main_v2.py里面的训练流程main函数和验证计算val函数就会发现,在计算准确率的时候,分母使用的是max_i * val_batchsize。而max_i是直接传递了1000进去。对于很大规模的数据集,验证集的总batch数量大于1000的情况下,这样计算的准确率是没问题的。但是对于规模较小的数据集,实际的batch数量根本就没有1000这么多,这就导致val函数算出来的准确率是不准确,而且偏小的。你可以修改一下这里的代码,在val函数中使用实际的batch数量来计算分母。

-------- 我是分割线 ------- 以我用这个repo做自己项目(文字内容与你的类似,也是符号、数字、英文)的经历来谈,主要调整过这几个方面:

1. 字典文件,repo里面自带的字典包含了字母、数字、符号、简体、繁体,对于我的项目来说涵盖太多,做了修改。

2. 模型读取图片时候的放缩参数(params.py里面设置),仓库原始针对的是32 * 160的白底黑字的训练集,每张图片上10个字符,测试也是将图片放缩至32像素高度。这个32目前是内部的CRNN模型写死的,但是160的像素宽度对应10个字符,这个在你自己的数据集上不一定合适(比如“战”和“占戈”,这两种字体宽度就不一样),可以调整。

3. params.py里还有一些参数可以调整,比如对图片进行标准化时候的均值与标准差这两个参数。

4. 你的训练集和测试集,理想状态下测试集与训练集应该服从同样的分布,这样才能期望模型在训练集上学到的东西可以很好的应用到测试集的识别上。

5. 另外,对于一般的OCR项目,原始的训练集可能规模较小,我自己的原始训练集只有2W张左右,通过各种手段,例如人工的文字图片合成、对原始训练集进行数据增强扩充到了100W的规模

6. 最后,改repo背后的CRNN结构。目前的CRNN是写死的,只能应用于32像素高度的图片,这是可以修改的。我自己项目里的图片由于本身质量不高,比较模糊,放缩到32像素高度更看不清楚了,就不要指望模型能学到什么有用的东西了。最后我们组还改了模型的细节,让网络适应64像素高度和96像素高度的图片。
   最后通过这些方面的修改,我自己的项目里测试准确率达到99%+。

感谢大佬的回复, 不好意思隔了这么久才看到。 关于之前的问题,我已经找到原因。是因为pytorch自带的CTCLoss计算出现问题,在我自己下载并编译了CTCloss之后,引入到项目中,loss和acc的计算就正确了。目前测试的流程和准确率也和大佬相似。Pytorch自带的ctcloss计算可能是由于环境原因,目前也没有调查出来。所以有同样Loss计算问题的朋友尝试自己安装CTCloss,把'' criterion = torch.nn.CTCLoss(reduction='sum') " 改为 " criterion = CTCLoss() ",重新尝试一下.

shihuangxiong commented 4 years ago

之前网络不好,没有刷出来楼主你的贴图,今天终于看到图片了。楼主你看你的结果截图里,实际上展示出来的识别细节结果那十条都是正确的吧。即使截图上显示的准确率是0.31,也不会这么巧展示出来的都识别正确了吧。 实际上你看下训练代码 crnn_main_v2.py里面的训练流程main函数和验证计算val函数就会发现,在计算准确率的时候,分母使用的是max_i * val_batchsize。而max_i是直接传递了1000进去。对于很大规模的数据集,验证集的总batch数量大于1000的情况下,这样计算的准确率是没问题的。但是对于规模较小的数据集,实际的batch数量根本就没有1000这么多,这就导致val函数算出来的准确率是不准确,而且偏小的。你可以修改一下这里的代码,在val函数中使用实际的batch数量来计算分母。 -------- 我是分割线 ------- 以我用这个repo做自己项目(文字内容与你的类似,也是符号、数字、英文)的经历来谈,主要调整过这几个方面:

1. 字典文件,repo里面自带的字典包含了字母、数字、符号、简体、繁体,对于我的项目来说涵盖太多,做了修改。

2. 模型读取图片时候的放缩参数(params.py里面设置),仓库原始针对的是32 * 160的白底黑字的训练集,每张图片上10个字符,测试也是将图片放缩至32像素高度。这个32目前是内部的CRNN模型写死的,但是160的像素宽度对应10个字符,这个在你自己的数据集上不一定合适(比如“战”和“占戈”,这两种字体宽度就不一样),可以调整。

3. params.py里还有一些参数可以调整,比如对图片进行标准化时候的均值与标准差这两个参数。

4. 你的训练集和测试集,理想状态下测试集与训练集应该服从同样的分布,这样才能期望模型在训练集上学到的东西可以很好的应用到测试集的识别上。

5. 另外,对于一般的OCR项目,原始的训练集可能规模较小,我自己的原始训练集只有2W张左右,通过各种手段,例如人工的文字图片合成、对原始训练集进行数据增强扩充到了100W的规模

6. 最后,改repo背后的CRNN结构。目前的CRNN是写死的,只能应用于32像素高度的图片,这是可以修改的。我自己项目里的图片由于本身质量不高,比较模糊,放缩到32像素高度更看不清楚了,就不要指望模型能学到什么有用的东西了。最后我们组还改了模型的细节,让网络适应64像素高度和96像素高度的图片。
   最后通过这些方面的修改,我自己的项目里测试准确率达到99%+。

感谢大佬的回复, 不好意思隔了这么久才看到。 关于之前的问题,我已经找到原因。是因为pytorch自带的CTCLoss计算出现问题,在我自己下载并编译了CTCloss之后,引入到项目中,loss和acc的计算就正确了。目前测试的流程和准确率也和大佬相似。Pytorch自带的ctcloss计算可能是由于环境原因,目前也没有调查出来。所以有同样Loss计算问题的朋友尝试自己安装CTCloss,把'' criterion = torch.nn.CTCLoss(reduction='sum') " 改为 " criterion = CTCLoss() ",重新尝试一下.

请问你用的是第三方的CTCloss吗?是不是用的torch-baidu-ctc这个库啊?但是这个库win10 cpu版本安装不上不知道啥原因。

shihuangxiong commented 4 years ago

请问大佬,可以分享下您的网络结构吗??在做毕业设计遇到瓶颈了。。。

发送自 Windows 10 版邮件https://go.microsoft.com/fwlink/?LinkId=550986应用


发件人: Chao Cheng notifications@github.com 发送时间: Wednesday, February 5, 2020 9:27:17 PM 收件人: Sierkinhane/crnn_chinese_characters_rec crnn_chinese_characters_rec@noreply.github.com 抄送: shihuangxiong shihuangxiong@outlook.com; Comment comment@noreply.github.com 主题: Re: [Sierkinhane/crnn_chinese_characters_rec] 关于训练准确率高于90%的前辈们,可否分享一下经验 (#175)

以我用这个repo做自己项目(文字内容与你的类似,也是符号、数字、英文)的经历来谈,主要调整过这几个方面:

  1. 字典文件,repo里面自带的字典包含了字母、数字、符号、简体、繁体,对于我的项目来说涵盖太多,做了修改。
  2. 模型读取图片时候的放缩参数(params.py里面设置),仓库原始针对的是32 * 160的白底黑字的训练集,每张图片上10个字符,测试也是将图片放缩至32像素高度。这个32目前是内部的CRNN模型写死的,但是160的像素宽度对应10个字符,这个在你自己的数据集上不一定合适(比如“战”和“占戈”,这两种字体宽度就不一样),可以调整。
  3. 你的训练集和测试集,理想状态下测试集与训练集应该服从同样的分布,这样才能期望模型在训练集上学到的东西可以很好的应用到测试集的识别上。
  4. 另外,对于一般的OCR项目,原始的训练集可能规模较小,我自己的原始训练集只有2W张左右,通过各种手段,例如人工的文字图片合成、对原始训练集进行数据增强扩充到了100W的规模
  5. 最后,改repo背后的CRNN结构。目前的CRNN是写死的,只能应用于32像素高度的图片,这是可以修改的。我自己项目里的图片由于本身质量不高,比较模糊,放缩到32像素高度更看不清楚了,就不要指望模型能学到什么有用的东西了。最后我们组还改了模型的细节,让网络适应64像素高度和96像素高度的图片。 最后通过这些方面的修改,我自己的项目里测试准确率达到99%+。

― You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/Sierkinhane/crnn_chinese_characters_rec/issues/175?email_source=notifications&email_token=AMINHLK6WLJFN5W2NNLELCLRBK5DLA5CNFSM4J6OT5T2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEK3NDGI#issuecomment-582406553, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AMINHLNOAFP4INSAUNNMPXLRBK5DLANCNFSM4J6OT5TQ.

Lowlowlowlowlowlow commented 4 years ago

@fenguoerbian 大佬,同求,请问如果想要训练更高宽度的图片,具体应该如何修改网络呢?

heyhumor commented 4 years ago

之前网络不好,没有刷出来楼主你的贴图,今天终于看到图片了。楼主你看你的结果截图里,实际上展示出来的识别细节结果那十条都是正确的吧。即使截图上显示的准确率是0.31,也不会这么巧展示出来的都识别正确了吧。 实际上你看下训练代码 crnn_main_v2.py里面的训练流程main函数和验证计算val函数就会发现,在计算准确率的时候,分母使用的是max_i * val_batchsize。而max_i是直接传递了1000进去。对于很大规模的数据集,验证集的总batch数量大于1000的情况下,这样计算的准确率是没问题的。但是对于规模较小的数据集,实际的batch数量根本就没有1000这么多,这就导致val函数算出来的准确率是不准确,而且偏小的。你可以修改一下这里的代码,在val函数中使用实际的batch数量来计算分母。 -------- 我是分割线 ------- 以我用这个repo做自己项目(文字内容与你的类似,也是符号、数字、英文)的经历来谈,主要调整过这几个方面:

1. 字典文件,repo里面自带的字典包含了字母、数字、符号、简体、繁体,对于我的项目来说涵盖太多,做了修改。

2. 模型读取图片时候的放缩参数(params.py里面设置),仓库原始针对的是32 * 160的白底黑字的训练集,每张图片上10个字符,测试也是将图片放缩至32像素高度。这个32目前是内部的CRNN模型写死的,但是160的像素宽度对应10个字符,这个在你自己的数据集上不一定合适(比如“战”和“占戈”,这两种字体宽度就不一样),可以调整。

3. params.py里还有一些参数可以调整,比如对图片进行标准化时候的均值与标准差这两个参数。

4. 你的训练集和测试集,理想状态下测试集与训练集应该服从同样的分布,这样才能期望模型在训练集上学到的东西可以很好的应用到测试集的识别上。

5. 另外,对于一般的OCR项目,原始的训练集可能规模较小,我自己的原始训练集只有2W张左右,通过各种手段,例如人工的文字图片合成、对原始训练集进行数据增强扩充到了100W的规模

6. 最后,改repo背后的CRNN结构。目前的CRNN是写死的,只能应用于32像素高度的图片,这是可以修改的。我自己项目里的图片由于本身质量不高,比较模糊,放缩到32像素高度更看不清楚了,就不要指望模型能学到什么有用的东西了。最后我们组还改了模型的细节,让网络适应64像素高度和96像素高度的图片。
   最后通过这些方面的修改,我自己的项目里测试准确率达到99%+。

感谢大佬的回复, 不好意思隔了这么久才看到。 关于之前的问题,我已经找到原因。是因为pytorch自带的CTCLoss计算出现问题,在我自己下载并编译了CTCloss之后,引入到项目中,loss和acc的计算就正确了。目前测试的流程和准确率也和大佬相似。Pytorch自带的ctcloss计算可能是由于环境原因,目前也没有调查出来。所以有同样Loss计算问题的朋友尝试自己安装CTCloss,把'' criterion = torch.nn.CTCLoss(reduction='sum') " 改为 " criterion = CTCLoss() ",重新尝试一下.

请问你用的是第三方的CTCloss吗?是不是用的torch-baidu-ctc这个库啊?但是这个库win10 cpu版本安装不上不知道啥原因。

我在Ubuntu18上安装的,库是github上的,https://github.com/SeanNaren/warp-ctc.git,可以参考这个教程试试 https://blog.csdn.net/u011622208/article/details/87620120

heyhumor commented 4 years ago

我的准确率一直为0,什么情况哎?我用的他给出大的数据集

多少迭代一直为零?可以先用小批次数据集测试一下模型是否可用,小批次的几个迭代acc就接近100%了。

fenguoerbian commented 4 years ago

@Lowlowlowlowlowlow 在models/crnn.py文件里是对模型的定义。可以看到里面的卷积部分结构是写死的,这里可以根据自己的需求修改。然后注意在forward 函数里向前传递的时候要保证h是1,原始的网络配原始的输入图片尺寸是自然满足的。你修改了网络的卷积部分之后,那就要在卷积的结果进LSTM之前要把高度拉到1。剩下就是外面配置文件、预处理等代码里面里相应的修改你的图片高度宽度了。

Tony1236 commented 4 years ago

@Lowlowlowlowlowlow 在models/crnn.py文件里是对模型的定义。可以看到里面的卷积部分结构是写死的,这里可以根据自己的需求修改。然后注意在forward 函数里向前传递的时候要保证h是1,原始的网络配原始的输入图片尺寸是自然满足的。你修改了网络的卷积部分之后,那就要在卷积的结果进LSTM之前要把高度拉到1。剩下就是外面配置文件、预处理等代码里面里相应的修改你的图片高度宽度了。

大佬,请教个问题,训练模型你用的是第三方的CTCloss,还是pytorch自带的ctcloss

Sierkinhane commented 4 years ago

@Tony1236 我更新了仓库,用pytorch1.2.0 cuda10 ctcloss没有出现问题

fenguoerbian commented 4 years ago

@Tony1236 我一直用的pytorch的ctcloss,没有出过问题。

shihuangxiong commented 4 years ago

@Tony1236 我一直用的pytorch的ctcloss,没有出过问题。 但是我训练的时候,损失会下降到6左右,测试精度一直为0.

Tony1236 commented 4 years ago

@Tony1236 我一直用的pytorch的ctcloss,没有出过问题。

恩,我用pytorch的ctcloss也没有出现问题,调整图片的高度和宽度,就是要在网络的结构中增加卷积和pool操作,对吧

Tony1236 commented 4 years ago

@Tony1236 我一直用的pytorch的ctcloss,没有出过问题。

恩,我用pytorch的ctcloss也没有出现问题,调整图片的高度和宽度,就是要在网络的结构中增加卷积和pool操作,对吧