Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

请问如果想使用该模型训练非captcha库内的图片,应该怎么修改呢? #45

Open
charfole opened this issue Nov 3, 2019 · 20 comments
Labels
数据增强 如何使用数据增强提高模型的泛化能力 自定义数据 如何使用自定义数据

Comments

@charfole
Copy link

charfole commented Nov 3, 2019

假设训练集中共有10000张图片,在D盘下的test子目录下,图片从1.jpg-10000.jpg。

@charfole charfole changed the title 请问如果想使用该模型训练非captcha库内的图片,应该怎没修改呢? 请问如果想使用该模型训练非captcha库内的图片,应该怎么修改呢? Nov 3, 2019
@ypwhs
Copy link
Owner

ypwhs commented Nov 3, 2019

#43 (comment)

@charfole
Copy link
Author

charfole commented Nov 3, 2019

感谢,我去尝试一下。btw,想请问一下我用colab上跑cnn_2019.ipynb中的训练模型单元格,发现运行完第11个epoch之后就停止继续训练了,这是为什么呢?

@ypwhs
Copy link
Owner

ypwhs commented Nov 3, 2019

感谢,我去尝试一下。btw,想请问一下我用colab上跑cnn_2019.ipynb中的训练模型单元格,发现运行完第11个epoch之后就停止继续训练了,这是为什么呢?

如果没有报错信息,可能是网络断了。

@chajnoven
Copy link

chajnoven commented Nov 4, 2019

感谢,我去尝试一下。btw,想请问一下我用colab上跑cnn_2019.ipynb中的训练模型单元格,发现运行完第11个epoch之后就停止继续训练了,这是为什么呢?

如果没有报错信息,可能是网络断了。

def __len__(self):
        return self.steps

您好,我想请问下关于这段steps是什么意思? 只知道batch_size是生成的图片数量

@ypwhs
Copy link
Owner

ypwhs commented Nov 4, 2019

感谢,我去尝试一下。btw,想请问一下我用colab上跑cnn_2019.ipynb中的训练模型单元格,发现运行完第11个epoch之后就停止继续训练了,这是为什么呢?

如果没有报错信息,可能是网络断了。

def __len__(self):
        return self.steps

您好,我想请问下关于这段steps是什么意思? 只知道batch_size是生成的图片数量

这代表每一代训练多少个 batch,比如按照下面的代码初始化数据集:

train_data = CaptchaSequence(characters, batch_size=128, steps=1000)
valid_data = CaptchaSequence(characters, batch_size=128, steps=100)

训练的时候每一代会训练 1000 个 batch,相当于 128000 张图。

@charfole
Copy link
Author

charfole commented Nov 4, 2019

感谢,我去尝试一下。btw,想请问一下我用colab上跑cnn_2019.ipynb中的训练模型单元格,发现运行完第11个epoch之后就停止继续训练了,这是为什么呢?

如果没有报错信息,可能是网络断了。

def __len__(self):
        return self.steps

您好,我想请问下关于这段steps是什么意思? 只知道batch_size是生成的图片数量

这代表每一代训练多少个 batch,比如按照下面的代码初始化数据集:

train_data = CaptchaSequence(characters, batch_size=128, steps=1000)
valid_data = CaptchaSequence(characters, batch_size=128, steps=100)

训练的时候每一代会训练 1000 个 batch,相当于 128000 张图。

您好,请问每一代的意思就是一个epoch吗?假如自己的数据集不像是captcha库中的数据集一样,不能根据不同的字府随机搭配生成图片,而是固定的几万张图片,是不是就无法有这种类似于扩大数据集的效果呢?

@chajnoven
Copy link

感谢,我去尝试一下。btw,想请问一下我用colab上跑cnn_2019.ipynb中的训练模型单元格,发现运行完第11个epoch之后就停止继续训练了,这是为什么呢?

如果没有报错信息,可能是网络断了。

def __len__(self):
        return self.steps

您好,我想请问下关于这段steps是什么意思? 只知道batch_size是生成的图片数量

这代表每一代训练多少个 batch,比如按照下面的代码初始化数据集:

train_data = CaptchaSequence(characters, batch_size=128, steps=1000)
valid_data = CaptchaSequence(characters, batch_size=128, steps=100)

训练的时候每一代会训练 1000 个 batch,相当于 128000 张图。

您好,请问每一代的意思就是一个epoch吗?假如自己的数据集不像是captcha库中的数据集一样,不能根据不同的字府随机搭配生成图片,而是固定的几万张图片,是不是就无法有这种类似于扩大数据集的效果呢?

可以做迁移,我目前在自己数据集10000的上面按照作者修改后测试集取得了%80+的效果

@charfole
Copy link
Author

charfole commented Nov 5, 2019

感谢,我去尝试一下。btw,想请问一下我用colab上跑cnn_2019.ipynb中的训练模型单元格,发现运行完第11个epoch之后就停止继续训练了,这是为什么呢?

如果没有报错信息,可能是网络断了。

def __len__(self):
        return self.steps

您好,我想请问下关于这段steps是什么意思? 只知道batch_size是生成的图片数量

这代表每一代训练多少个 batch,比如按照下面的代码初始化数据集:

train_data = CaptchaSequence(characters, batch_size=128, steps=1000)
valid_data = CaptchaSequence(characters, batch_size=128, steps=100)

训练的时候每一代会训练 1000 个 batch,相当于 128000 张图。

您好,请问每一代的意思就是一个epoch吗?假如自己的数据集不像是captcha库中的数据集一样,不能根据不同的字府随机搭配生成图片,而是固定的几万张图片,是不是就无法有这种类似于扩大数据集的效果呢?

可以做迁移,我目前在自己数据集10000的上面按照作者修改后测试集取得了%80+的效果

好的,感谢您。那请问能否在自己的图片数据集上做出类似于扩大数据集的操作吗?如果想进一步提升模型准确率的话,感觉10000张图片仍是有点少。

@ypwhs
Copy link
Owner

ypwhs commented Nov 5, 2019

感谢,我去尝试一下。btw,想请问一下我用colab上跑cnn_2019.ipynb中的训练模型单元格,发现运行完第11个epoch之后就停止继续训练了,这是为什么呢?

如果没有报错信息,可能是网络断了。

def __len__(self):
        return self.steps

您好,我想请问下关于这段steps是什么意思? 只知道batch_size是生成的图片数量

这代表每一代训练多少个 batch,比如按照下面的代码初始化数据集:

train_data = CaptchaSequence(characters, batch_size=128, steps=1000)
valid_data = CaptchaSequence(characters, batch_size=128, steps=100)

训练的时候每一代会训练 1000 个 batch,相当于 128000 张图。

您好,请问每一代的意思就是一个epoch吗?假如自己的数据集不像是captcha库中的数据集一样,不能根据不同的字府随机搭配生成图片,而是固定的几万张图片,是不是就无法有这种类似于扩大数据集的效果呢?

一代就是一个 epoch。

如果是固定几万张图片,也是需要训练多代的,通常来说需要训练 10 代以上才模型能收敛。

如果是固定的图片,你也可以使用数据生成器去对图片进行变换,参考:

@charfole
Copy link
Author

charfole commented Nov 5, 2019

Get it!
今晚上手的时候又遇到了一个小问题,关于分辨率的。
我刚刚用torch版本跑了我的训练集,分辨率是120*40,把height和width也改成和我的训练集一样的了,直接跑了,但是在epoch的那一环节,好像因为前面的torch.size因为分辨率的变化而导致无法训练。之前的torch.size为12,修改分辨率后为7。谢谢您的回答!
微信图片_20191105230512

@ypwhs
Copy link
Owner

ypwhs commented Nov 6, 2019

Get it!
今晚上手的时候又遇到了一个小问题,关于分辨率的。
我刚刚用torch版本跑了我的训练集,分辨率是120*40,把height和width也改成和我的训练集一样的了,直接跑了,但是在epoch的那一环节,好像因为前面的torch.size因为分辨率的变化而导致无法训练。之前的torch.size为12,修改分辨率后为7。谢谢您的回答!
微信图片_20191105230512

在最前面把 n_input_length 改成 7 就好了:

n_input_length = 7

@charfole
Copy link
Author

charfole commented Nov 7, 2019

Get it!
今晚上手的时候又遇到了一个小问题,关于分辨率的。
我刚刚用torch版本跑了我的训练集,分辨率是120*40,把height和width也改成和我的训练集一样的了,直接跑了,但是在epoch的那一环节,好像因为前面的torch.size因为分辨率的变化而导致无法训练。之前的torch.size为12,修改分辨率后为7。谢谢您的回答!
微信图片_20191105230512

在最前面把 n_input_length 改成 7 就好了:

n_input_length = 7

好的!感谢!不过修改后正确率有所下降,可能与网络本来的结构有关?
BTW,先对训练集中的图片做二值化和降噪的处理,然后再数据增强会不会能让该模型准确率更高一点?如果会的话,请问有这方面操作比较好的代码吗?

@ypwhs
Copy link
Owner

ypwhs commented Nov 8, 2019

Get it!
今晚上手的时候又遇到了一个小问题,关于分辨率的。
我刚刚用torch版本跑了我的训练集,分辨率是120*40,把height和width也改成和我的训练集一样的了,直接跑了,但是在epoch的那一环节,好像因为前面的torch.size因为分辨率的变化而导致无法训练。之前的torch.size为12,修改分辨率后为7。谢谢您的回答!
微信图片_20191105230512

在最前面把 n_input_length 改成 7 就好了:

n_input_length = 7

好的!感谢!不过修改后正确率有所下降,可能与网络本来的结构有关?
BTW,先对训练集中的图片做二值化和降噪的处理,然后再数据增强会不会能让该模型准确率更高一点?如果会的话,请问有这方面操作比较好的代码吗?

  1. 可以增加数据,数据越多越好。
  2. 不需要做二值化和降噪,除非你确定你的操作不会丢失信息。因为卷积层可以学会如何去做降噪和二值化,如果这样做能让 loss 降低,卷积层会自动做这个操作。另外数据增强可以提高模型的泛化能力。

数据增强参考教程:https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html

transforms.Compose([
    transforms.RandomResizedCrop(224),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])

其中的 transforms 需要根据你的问题进行调整,具体参考文档:https://pytorch.org/docs/stable/torchvision/transforms.html

@charfole
Copy link
Author

charfole commented Nov 9, 2019

Get it!
今晚上手的时候又遇到了一个小问题,关于分辨率的。
我刚刚用torch版本跑了我的训练集,分辨率是120*40,把height和width也改成和我的训练集一样的了,直接跑了,但是在epoch的那一环节,好像因为前面的torch.size因为分辨率的变化而导致无法训练。之前的torch.size为12,修改分辨率后为7。谢谢您的回答!
微信图片_20191105230512

在最前面把 n_input_length 改成 7 就好了:

n_input_length = 7

好的!感谢!不过修改后正确率有所下降,可能与网络本来的结构有关?
BTW,先对训练集中的图片做二值化和降噪的处理,然后再数据增强会不会能让该模型准确率更高一点?如果会的话,请问有这方面操作比较好的代码吗?

  1. 可以增加数据,数据越多越好。
  2. 不需要做二值化和降噪,除非你确定你的操作不会丢失信息。因为卷积层可以学会如何去做降噪和二值化,如果这样做能让 loss 降低,卷积层会自动做这个操作。另外数据增强可以提高模型的泛化能力。

数据增强参考教程:https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html

transforms.Compose([
    transforms.RandomResizedCrop(224),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])

其中的 transforms 需要根据你的问题进行调整,具体参考文档:https://pytorch.org/docs/stable/torchvision/transforms.html

好的,十分感谢。现有的小问题大概就是如何增强数据集了。增强数据集时,我发现旋转操作会导致验证码的四周出现一些黑边,不知道这样是否会影响准确率?如果会影响的话,更值得推荐的数据增强操作应该是哪些?
个人认为对于验证码,不太适合使用对称,缩放等操作,如果使用锐化、模糊、加噪等方法效果是否会更优呢?
再次感谢您一直以来的耐心回复。

@ypwhs
Copy link
Owner

ypwhs commented Nov 9, 2019

Get it!
今晚上手的时候又遇到了一个小问题,关于分辨率的。
我刚刚用torch版本跑了我的训练集,分辨率是120*40,把height和width也改成和我的训练集一样的了,直接跑了,但是在epoch的那一环节,好像因为前面的torch.size因为分辨率的变化而导致无法训练。之前的torch.size为12,修改分辨率后为7。谢谢您的回答!
微信图片_20191105230512

在最前面把 n_input_length 改成 7 就好了:

n_input_length = 7

好的!感谢!不过修改后正确率有所下降,可能与网络本来的结构有关?
BTW,先对训练集中的图片做二值化和降噪的处理,然后再数据增强会不会能让该模型准确率更高一点?如果会的话,请问有这方面操作比较好的代码吗?

  1. 可以增加数据,数据越多越好。
  2. 不需要做二值化和降噪,除非你确定你的操作不会丢失信息。因为卷积层可以学会如何去做降噪和二值化,如果这样做能让 loss 降低,卷积层会自动做这个操作。另外数据增强可以提高模型的泛化能力。

数据增强参考教程:https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html

transforms.Compose([
    transforms.RandomResizedCrop(224),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])

其中的 transforms 需要根据你的问题进行调整,具体参考文档:https://pytorch.org/docs/stable/torchvision/transforms.html

好的,十分感谢。现有的小问题大概就是如何增强数据集了。增强数据集时,我发现旋转操作会导致验证码的四周出现一些黑边,不知道这样是否会影响准确率?如果会影响的话,更值得推荐的数据增强操作应该是哪些?
个人认为对于验证码,不太适合使用对称,缩放等操作,如果使用锐化、模糊、加噪等方法效果是否会更优呢?
再次感谢您一直以来的耐心回复。

旋转有一个参数 fill 可以控制图片以外的颜色该如何补全,参考链接:https://pytorch.org/docs/stable/torchvision/transforms.html#torchvision.transforms.RandomRotation

理论上数据集的分布需要和实际数据一致,如果实际数据没有黑边,那么训练数据就不应该存在黑边。

对称不应该使用,缩放可以使用,其他方法以数据实际情况为准,如果数据存在模糊情况,那么添加随机的模糊可以增强模型对真实数据的泛化能力。

例如识别用户拍摄的照片中的文字,存在仿射变换问题,如果增加随机仿射变换,即可加强模型对用户在不同角度下拍摄的图片的识别效果。

@ypwhs ypwhs added 数据增强 如何使用数据增强提高模型的泛化能力 自定义数据 如何使用自定义数据 labels Nov 9, 2019
@charfole
Copy link
Author

charfole commented Nov 10, 2019

Get it!
今晚上手的时候又遇到了一个小问题,关于分辨率的。
我刚刚用torch版本跑了我的训练集,分辨率是120*40,把height和width也改成和我的训练集一样的了,直接跑了,但是在epoch的那一环节,好像因为前面的torch.size因为分辨率的变化而导致无法训练。之前的torch.size为12,修改分辨率后为7。谢谢您的回答!
微信图片_20191105230512

在最前面把 n_input_length 改成 7 就好了:

n_input_length = 7

好的!感谢!不过修改后正确率有所下降,可能与网络本来的结构有关?
BTW,先对训练集中的图片做二值化和降噪的处理,然后再数据增强会不会能让该模型准确率更高一点?如果会的话,请问有这方面操作比较好的代码吗?

  1. 可以增加数据,数据越多越好。
  2. 不需要做二值化和降噪,除非你确定你的操作不会丢失信息。因为卷积层可以学会如何去做降噪和二值化,如果这样做能让 loss 降低,卷积层会自动做这个操作。另外数据增强可以提高模型的泛化能力。

数据增强参考教程:https://pytorch.org/tutorials/beginner/transfer_learning_tutorial.html

transforms.Compose([
    transforms.RandomResizedCrop(224),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])

其中的 transforms 需要根据你的问题进行调整,具体参考文档:https://pytorch.org/docs/stable/torchvision/transforms.html

好的,十分感谢。现有的小问题大概就是如何增强数据集了。增强数据集时,我发现旋转操作会导致验证码的四周出现一些黑边,不知道这样是否会影响准确率?如果会影响的话,更值得推荐的数据增强操作应该是哪些?
个人认为对于验证码,不太适合使用对称,缩放等操作,如果使用锐化、模糊、加噪等方法效果是否会更优呢?
再次感谢您一直以来的耐心回复。

旋转有一个参数 fill 可以控制图片以外的颜色该如何补全,参考链接:https://pytorch.org/docs/stable/torchvision/transforms.html#torchvision.transforms.RandomRotation

理论上数据集的分布需要和实际数据一致,如果实际数据没有黑边,那么训练数据就不应该存在黑边。

对称不应该使用,缩放可以使用,其他方法以数据实际情况为准,如果数据存在模糊情况,那么添加随机的模糊可以增强模型对真实数据的泛化能力。

例如识别用户拍摄的照片中的文字,存在仿射变换问题,如果增加随机仿射变换,即可加强模型对用户在不同角度下拍摄的图片的识别效果。

好的,再次感谢您的回答!
BTW,下午初测了一下进行旋转并且填充白色操作后的模型,数据集从5000增强到了15000左右,很遗憾的是,5000张测试集上的准确率从80下降到了60。个人分析的原因可能是由于训练集中的验证码的底色不断在变化,因此旋转后只填充白色,好像效果不太好,但又想不到其他更好的方法。
另外,由于与您本身训练该模型的训练集不一样,我们的训练集规模只有15000张,不知道这种情况下是否需要修改batch_size和epoch数才能更好地贴合模型呢?如果需要的话,又应该向着什么方向修改呢?

@ypwhs
Copy link
Owner

ypwhs commented Nov 10, 2019

使用此库可以按背景颜色进行填充:https://github.com/aleju/imgaug

在 Affine 的 API 里有一个参数叫 mode,可以控制 padding 的方式:

mode (str or list of str or imgaug.ALL or imgaug.parameters.StochasticParameter, optional) – Method to use when filling in newly created pixels. Same meaning as in skimage (and numpy.pad()):

  • constant: Pads with a constant value
  • edge: Pads with the edge values of array
  • symmetric: Pads with the reflection of the vector mirrored along the edge of the array.
    reflect: Pads with the reflection of the vector mirrored on the first and last values of the vector along each axis.
  • wrap: Pads with the wrap of the vector along the axis. The first values are used to pad the end and the end values are used to pad the beginning.

参考图:

如果你的验证码图片背景颜色是纯色,可以使用 edge 模式,根据边界颜色进行补全。

修改 batch_size 和 epoch 只能提高模型拟合数据的程度,不能改变上限,数据决定模型识别效果的上限。如果你想提高模型的识别精度,目前最好的方法是提高数据量。

@charfole
Copy link
Author

好的,了解,等下尝试一下edge参数!但是我发现在训练的过程中,会连续有很多个epoch的loss都出现了负数的情况,这会不会说明了一些问题呢?loss一般是-0.001--0.01不等。训练集的准确率则稳定在百分之九十上下。

@ypwhs
Copy link
Owner

ypwhs commented Nov 10, 2019

loss 是不可以为负的,请检查代码或数据的正确性。

首先找到导致 loss 为负的样本,然后使用模型对该样本进行预测,查看预测结果是否合理,然后计算 loss,一步步 debug 代码哪里有问题。

@ctzhang2008
Copy link

ctzhang2008 commented Mar 13, 2021

假设训练集中共有10000张图片,在D盘下的test子目录下,图片从1.jpg-10000.jpg。

batch_size, width, height, n_len, n_class = 128, 160, 60, 4, len(characters)

file_path = r'd:/test/'
filenames = os.listdir(file_path)

class CaptchaSequence(Sequence):
def init(self, characters, batch_size, steps, n_len=4, width=160, height=60):
self.characters = characters
self.batch_size = batch_size
self.steps = steps
self.n_len = n_len
self.width = width
self.height = height
self.n_class = len(characters)

  def __len__(self):
        return self.steps

  def __getitem__(self, idx):
        X = np.zeros((self.batch_size, self.height, self.width, 3), dtype=np.float32)
        y = [np.zeros((self.batch_size, self.n_class), dtype=np.uint8) for i in range(self.n_len)]
        for i in range(self.batch_size):
            random_str = random.choice(filenames)
            img = Image.open(file_path + random_str)
            X[i] = np.array(img) / 255.0

            random_str = str(random_str.split('.')[0])

            for j, ch in enumerate(random_str):
                y[j][i, :] = 0
                y[j][i, self.characters.find(ch)] = 1
        return X, y

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
数据增强 如何使用数据增强提高模型的泛化能力 自定义数据 如何使用自定义数据
Projects
None yet
Development

No branches or pull requests

4 participants