ML.NET: 为什么我必须训练预训练模型?
ML.NET: Why do I have to train a pretrained model?
我想使用预训练模型(如 inceptionV1/V3)进行图像分类。
所以我在 ML.NET 中设置了一个管道,我在其中加载了这个 TensorFlow 模型。但是在我发现的每一个教程中,都表明你必须在之后训练该模型才能获得模型。
例如这里:
https://docs.microsoft.com/en-US/dotnet/machine-learning/tutorials/image-classification
=> 使用上面加载的数据训练模型:
=> ITransformer 模型 = pipeline.Fit(trainingData);
为什么不能在没有训练数据的情况下调用 Fit()。因为我只想使用原始加载的模型而不进行修改。它已经由 Google 使用数百万张图片进行训练,应该足以满足我的所有需求。
感谢您的建议!
实际上,您永远不会从零开始重新训练完整的模型,只是最后几个 layers.The 顶层学习非常普遍的特征,随着我们深入网络,这些层倾向于学习更针对任务的模式我们正在处理。事实上,我们正在根据我们的特定需求微调模型。
您不必再次训练模型。只需加载它,然后使用它进行预测。问题是模型是在 imagenet 数据集上训练的。这个数据集有 1000 class 个。您的图片类型可能包含也可能不包含在 1000 class 中。要为您的应用程序定制模型,您应该使用您的定制数据集对其进行训练。例如,如果你有一个包含 250 classes 鸟类的训练集,每个 class 都有一个单独的目录,并且你想 classify 鸟类,那么你应该使用如下的 Inception 模型。我
img_size= (224,224) # set this to the size of images you want to use
img_shape=(224,224,3) # set this to the input image shape
no_of_classes =250 # set this to an integer value for the number of classes
train_dir=r'c:\birds\train' #point this to your training directory'
t_gen=ImageDataGenerator(preprocessing_function=tf.keras.applications.inception_v3.preprocess_input, validation_split=0.3)
train_gen=t_gen.flow_from_directory( directory= train_dir, target_size=img_size,
class_mode="categorical", batch_size=32, shuffle=True, seed=123,
subset='training)
valid_gen=t_gen.flow_from_directory(directory= train_dir, target_size=img_size,
class_mode="categorical", batch_size=32, shuffle=False, seed=123,
subset='validation')
base_model=tf.keras.applications.InceptionV3( include_top=False, weights="imagenet",
input_shape=img_shape, pooling='max')
x=basemodel.output
x= Dense(512, activation-'relu')(x)
x= Dropout(.3)(x)
output=Dense(no_of_classes, activation='softmax')(x)
model=Model(inputs=base_model.input, outputs=output)
model.compile(Adam(lr=.001), loss='categorical_crossentropy', metrics=['accuracy'])
history==model.fit(x=train_gen, epochs=20, verbose=2,
validation_data=valid_gen, shuffle=False, initial_epoch=0)
感谢您的回答,但它并没有解决我最初的问题,即我无法在没有训练的情况下获得模型。
所以对于有同样问题的其他人,我找到了一个解决方法:
我没有使用 ML.NET 来加载初始模型,但我现在使用 TensorFlow.NET nuget 包来加载初始模型。在那里我可以加载一个预训练模型并使用它。
这是我使用的示例项目的 link:
https://github.com/SciSharp/SciSharp-Stack-Examples/tree/master/src/TensorFlowNET.Examples/ImageProcessing
有 2 个很好的例子可以满足我的需要:
- 文件 ImageRecognitionInception.cs 包含一个用于图像分类的 InceptionV1 模型(注意:在顶部的评论中有站立的 InceptionV3 但这是错误的。这个文件肯定使用 InceptionV1 模型 - 你可以很容易地通过 224 像素的图像分辨率看到这个。InceptionV3 使用 299 像素的图像)。
- 文件 InceptionArchGoogLeNet.cs 包含一个用于图像分类的 InceptionV3 模型。
我希望这对那些也在寻找一种无需重新训练即可加载预训练模型的简单方法的人有所帮助。
只需向 Fit
方法传递一个空数据集,例如
let tf = mlContext.Model.LoadTensorFlowModel modelLocation
let pipeline = tf.ScoreTensorFlowModel("OutputNode", "InputNode", addBatchDimensionInput = false)
let data = mlContext.Data.LoadFromEnumerable(Seq.empty<InputType>)
let model = pipeline.Fit(data)
这将加载模型并在不修改 tensorflow 模型的情况下为您提供转换器。
我想使用预训练模型(如 inceptionV1/V3)进行图像分类。
所以我在 ML.NET 中设置了一个管道,我在其中加载了这个 TensorFlow 模型。但是在我发现的每一个教程中,都表明你必须在之后训练该模型才能获得模型。
例如这里: https://docs.microsoft.com/en-US/dotnet/machine-learning/tutorials/image-classification
=> 使用上面加载的数据训练模型: => ITransformer 模型 = pipeline.Fit(trainingData);
为什么不能在没有训练数据的情况下调用 Fit()。因为我只想使用原始加载的模型而不进行修改。它已经由 Google 使用数百万张图片进行训练,应该足以满足我的所有需求。
感谢您的建议!
实际上,您永远不会从零开始重新训练完整的模型,只是最后几个 layers.The 顶层学习非常普遍的特征,随着我们深入网络,这些层倾向于学习更针对任务的模式我们正在处理。事实上,我们正在根据我们的特定需求微调模型。
您不必再次训练模型。只需加载它,然后使用它进行预测。问题是模型是在 imagenet 数据集上训练的。这个数据集有 1000 class 个。您的图片类型可能包含也可能不包含在 1000 class 中。要为您的应用程序定制模型,您应该使用您的定制数据集对其进行训练。例如,如果你有一个包含 250 classes 鸟类的训练集,每个 class 都有一个单独的目录,并且你想 classify 鸟类,那么你应该使用如下的 Inception 模型。我
img_size= (224,224) # set this to the size of images you want to use
img_shape=(224,224,3) # set this to the input image shape
no_of_classes =250 # set this to an integer value for the number of classes
train_dir=r'c:\birds\train' #point this to your training directory'
t_gen=ImageDataGenerator(preprocessing_function=tf.keras.applications.inception_v3.preprocess_input, validation_split=0.3)
train_gen=t_gen.flow_from_directory( directory= train_dir, target_size=img_size,
class_mode="categorical", batch_size=32, shuffle=True, seed=123,
subset='training)
valid_gen=t_gen.flow_from_directory(directory= train_dir, target_size=img_size,
class_mode="categorical", batch_size=32, shuffle=False, seed=123,
subset='validation')
base_model=tf.keras.applications.InceptionV3( include_top=False, weights="imagenet",
input_shape=img_shape, pooling='max')
x=basemodel.output
x= Dense(512, activation-'relu')(x)
x= Dropout(.3)(x)
output=Dense(no_of_classes, activation='softmax')(x)
model=Model(inputs=base_model.input, outputs=output)
model.compile(Adam(lr=.001), loss='categorical_crossentropy', metrics=['accuracy'])
history==model.fit(x=train_gen, epochs=20, verbose=2,
validation_data=valid_gen, shuffle=False, initial_epoch=0)
感谢您的回答,但它并没有解决我最初的问题,即我无法在没有训练的情况下获得模型。
所以对于有同样问题的其他人,我找到了一个解决方法: 我没有使用 ML.NET 来加载初始模型,但我现在使用 TensorFlow.NET nuget 包来加载初始模型。在那里我可以加载一个预训练模型并使用它。
这是我使用的示例项目的 link: https://github.com/SciSharp/SciSharp-Stack-Examples/tree/master/src/TensorFlowNET.Examples/ImageProcessing 有 2 个很好的例子可以满足我的需要:
- 文件 ImageRecognitionInception.cs 包含一个用于图像分类的 InceptionV1 模型(注意:在顶部的评论中有站立的 InceptionV3 但这是错误的。这个文件肯定使用 InceptionV1 模型 - 你可以很容易地通过 224 像素的图像分辨率看到这个。InceptionV3 使用 299 像素的图像)。
- 文件 InceptionArchGoogLeNet.cs 包含一个用于图像分类的 InceptionV3 模型。
我希望这对那些也在寻找一种无需重新训练即可加载预训练模型的简单方法的人有所帮助。
只需向 Fit
方法传递一个空数据集,例如
let tf = mlContext.Model.LoadTensorFlowModel modelLocation
let pipeline = tf.ScoreTensorFlowModel("OutputNode", "InputNode", addBatchDimensionInput = false)
let data = mlContext.Data.LoadFromEnumerable(Seq.empty<InputType>)
let model = pipeline.Fit(data)
这将加载模型并在不修改 tensorflow 模型的情况下为您提供转换器。