codemetic commited on
Commit
f145bd7
·
1 Parent(s): f502364

initial commit

Browse files
Files changed (8) hide show
  1. .cspell.json +6 -0
  2. .env.example +3 -0
  3. .gitignore +3 -0
  4. LICENSE +121 -0
  5. README.md +68 -0
  6. environment.yml +0 -0
  7. test.py +40 -0
  8. train.py +105 -0
.cspell.json ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ {
2
+ "words": [
3
+ "dotenv"
4
+ ],
5
+ "allowCompoundWords": true
6
+ }
.env.example ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ TRAIN_DATASET = /path/to/your/train-dataset
2
+ TEST_DATASET = /path/to/your/test-dataset
3
+ KMP_DUPLICATE_LIB_OK = TRUE # 避免 OpenMP 重复初始化错误。不要修改这一项
.gitignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ *.h5
2
+ .env
3
+ /test
LICENSE ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Creative Commons Legal Code
2
+
3
+ CC0 1.0 Universal
4
+
5
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
6
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
7
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
8
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
9
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
10
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
11
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
12
+ HEREUNDER.
13
+
14
+ Statement of Purpose
15
+
16
+ The laws of most jurisdictions throughout the world automatically confer
17
+ exclusive Copyright and Related Rights (defined below) upon the creator
18
+ and subsequent owner(s) (each and all, an "owner") of an original work of
19
+ authorship and/or a database (each, a "Work").
20
+
21
+ Certain owners wish to permanently relinquish those rights to a Work for
22
+ the purpose of contributing to a commons of creative, cultural and
23
+ scientific works ("Commons") that the public can reliably and without fear
24
+ of later claims of infringement build upon, modify, incorporate in other
25
+ works, reuse and redistribute as freely as possible in any form whatsoever
26
+ and for any purposes, including without limitation commercial purposes.
27
+ These owners may contribute to the Commons to promote the ideal of a free
28
+ culture and the further production of creative, cultural and scientific
29
+ works, or to gain reputation or greater distribution for their Work in
30
+ part through the use and efforts of others.
31
+
32
+ For these and/or other purposes and motivations, and without any
33
+ expectation of additional consideration or compensation, the person
34
+ associating CC0 with a Work (the "Affirmer"), to the extent that he or she
35
+ is an owner of Copyright and Related Rights in the Work, voluntarily
36
+ elects to apply CC0 to the Work and publicly distribute the Work under its
37
+ terms, with knowledge of his or her Copyright and Related Rights in the
38
+ Work and the meaning and intended legal effect of CC0 on those rights.
39
+
40
+ 1. Copyright and Related Rights. A Work made available under CC0 may be
41
+ protected by copyright and related or neighboring rights ("Copyright and
42
+ Related Rights"). Copyright and Related Rights include, but are not
43
+ limited to, the following:
44
+
45
+ i. the right to reproduce, adapt, distribute, perform, display,
46
+ communicate, and translate a Work;
47
+ ii. moral rights retained by the original author(s) and/or performer(s);
48
+ iii. publicity and privacy rights pertaining to a person's image or
49
+ likeness depicted in a Work;
50
+ iv. rights protecting against unfair competition in regards to a Work,
51
+ subject to the limitations in paragraph 4(a), below;
52
+ v. rights protecting the extraction, dissemination, use and reuse of data
53
+ in a Work;
54
+ vi. database rights (such as those arising under Directive 96/9/EC of the
55
+ European Parliament and of the Council of 11 March 1996 on the legal
56
+ protection of databases, and under any national implementation
57
+ thereof, including any amended or successor version of such
58
+ directive); and
59
+ vii. other similar, equivalent or corresponding rights throughout the
60
+ world based on applicable law or treaty, and any national
61
+ implementations thereof.
62
+
63
+ 2. Waiver. To the greatest extent permitted by, but not in contravention
64
+ of, applicable law, Affirmer hereby overtly, fully, permanently,
65
+ irrevocably and unconditionally waives, abandons, and surrenders all of
66
+ Affirmer's Copyright and Related Rights and associated claims and causes
67
+ of action, whether now known or unknown (including existing as well as
68
+ future claims and causes of action), in the Work (i) in all territories
69
+ worldwide, (ii) for the maximum duration provided by applicable law or
70
+ treaty (including future time extensions), (iii) in any current or future
71
+ medium and for any number of copies, and (iv) for any purpose whatsoever,
72
+ including without limitation commercial, advertising or promotional
73
+ purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
74
+ member of the public at large and to the detriment of Affirmer's heirs and
75
+ successors, fully intending that such Waiver shall not be subject to
76
+ revocation, rescission, cancellation, termination, or any other legal or
77
+ equitable action to disrupt the quiet enjoyment of the Work by the public
78
+ as contemplated by Affirmer's express Statement of Purpose.
79
+
80
+ 3. Public License Fallback. Should any part of the Waiver for any reason
81
+ be judged legally invalid or ineffective under applicable law, then the
82
+ Waiver shall be preserved to the maximum extent permitted taking into
83
+ account Affirmer's express Statement of Purpose. In addition, to the
84
+ extent the Waiver is so judged Affirmer hereby grants to each affected
85
+ person a royalty-free, non transferable, non sublicensable, non exclusive,
86
+ irrevocable and unconditional license to exercise Affirmer's Copyright and
87
+ Related Rights in the Work (i) in all territories worldwide, (ii) for the
88
+ maximum duration provided by applicable law or treaty (including future
89
+ time extensions), (iii) in any current or future medium and for any number
90
+ of copies, and (iv) for any purpose whatsoever, including without
91
+ limitation commercial, advertising or promotional purposes (the
92
+ "License"). The License shall be deemed effective as of the date CC0 was
93
+ applied by Affirmer to the Work. Should any part of the License for any
94
+ reason be judged legally invalid or ineffective under applicable law, such
95
+ partial invalidity or ineffectiveness shall not invalidate the remainder
96
+ of the License, and in such case Affirmer hereby affirms that he or she
97
+ will not (i) exercise any of his or her remaining Copyright and Related
98
+ Rights in the Work or (ii) assert any associated claims and causes of
99
+ action with respect to the Work, in either case contrary to Affirmer's
100
+ express Statement of Purpose.
101
+
102
+ 4. Limitations and Disclaimers.
103
+
104
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
105
+ surrendered, licensed or otherwise affected by this document.
106
+ b. Affirmer offers the Work as-is and makes no representations or
107
+ warranties of any kind concerning the Work, express, implied,
108
+ statutory or otherwise, including without limitation warranties of
109
+ title, merchantability, fitness for a particular purpose, non
110
+ infringement, or the absence of latent or other defects, accuracy, or
111
+ the present or absence of errors, whether or not discoverable, all to
112
+ the greatest extent permissible under applicable law.
113
+ c. Affirmer disclaims responsibility for clearing rights of other persons
114
+ that may apply to the Work or any use thereof, including without
115
+ limitation any person's Copyright and Related Rights in the Work.
116
+ Further, Affirmer disclaims responsibility for obtaining any necessary
117
+ consents, permissions or other rights required for any use of the
118
+ Work.
119
+ d. Affirmer understands and acknowledges that Creative Commons is not a
120
+ party to this document and has no duty or obligation with respect to
121
+ this CC0 or use of the Work.
README.md ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 机器学习 - 猫狗识别简单实现
2
+
3
+ 这是一个简单的基于 Tensorflow 的猫狗识别模型。用于入门机器学习以及了解机器学习中的基础概念。
4
+
5
+ ## 安装
6
+
7
+ 首先需要下载猫狗识别的数据集用于训练。可以参考在 HuggingFace 的 [Microsoft 的数据集](https://huggingface.co/datasets/microsoft/cats_vs_dogs)
8
+ 下载训练数据集后,需要做一些整理,先确保项目目录结构如下:
9
+
10
+ ```
11
+ train/
12
+ ├── cats/
13
+ │ ├── cat.0.jpg
14
+ │ ├── ....
15
+ |── dogs/
16
+ ├── dog.0.jpg
17
+ ├── ....
18
+ ```
19
+
20
+ 然后复制本项目中的 `.env.example` 一份到本目录,重命名为 `.env` 并修改内容,改成 train 目录的所在地
21
+
22
+ ```bash
23
+ TRAIN_DATASET = /path/to/your/dataset
24
+ ```
25
+
26
+ 然后在 conda 环境下安装依赖。
27
+
28
+ ```bash
29
+ conda create --name cat-vs-dog python=3.9 --file requirements.txt
30
+ ```
31
+
32
+ ## 训练
33
+
34
+ 执行命令
35
+
36
+ ```bash
37
+ python train.py
38
+ ```
39
+
40
+ 将会在本目录下生成 `cat_dog_model.h5` 模型文件。
41
+
42
+ ## 预测
43
+
44
+ 准备好测试数据集的目录,目录下只需存放图片即可。
45
+
46
+ 在 `.env` 文件中添加测试数据集的目录。
47
+
48
+ ```bash
49
+ TEST_DATASET = /path/to/your/dataset
50
+ ```
51
+
52
+ 请先确保你已经训练好了数据并正确生成了 `cat_dog_model.h5` 模型文件。
53
+
54
+ 如果你没条件训练,可以直接在本仓库的 Release 上[下载现有的模型](https://github.com/PrinOrange/dog-vs-cat/releases/tag/1.0.0)。
55
+
56
+
57
+ 然后执行命令
58
+
59
+ ```bash
60
+ python test.py
61
+ ```
62
+
63
+ 在命令台中会产生如下输出:
64
+
65
+ ```plaintext
66
+ The model predicts the image xxx.jpg is a cat, with sigmoid 0.9999812
67
+ ...
68
+ ```
environment.yml ADDED
Binary file (9.67 kB). View file
 
test.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from tensorflow.keras.models import load_model
2
+ from tensorflow.keras.preprocessing import image
3
+ import numpy as np
4
+ import os
5
+
6
+ # 加载模型
7
+ model = load_model("cat_dog_model.h5")
8
+
9
+ # 设置要处理的目录
10
+ input_dir = os.getenv("TEST_DATASET")
11
+
12
+ # 支持的图像扩展名
13
+ image_extensions = (".jpg", ".jpeg", ".png", ".bmp")
14
+
15
+ def predict(img_path):
16
+ img = image.load_img(img_path, target_size=(150, 150))
17
+ x = image.img_to_array(img) / 255.0
18
+ x = np.expand_dims(x, axis=0)
19
+ pred = model.predict(x)[0][0]
20
+
21
+ if pred < 0.3:
22
+ label = "cat"
23
+ elif pred > 0.7:
24
+ label = "dog"
25
+ else:
26
+ label = "uncertain animal"
27
+
28
+ return [label, pred]
29
+
30
+ # 遍历目录下所有图片文件
31
+ for fname in os.listdir(input_dir):
32
+ if not fname.lower().endswith(image_extensions):
33
+ continue # 跳过非图片文件
34
+ img_path = os.path.join(input_dir, fname)
35
+ try:
36
+ result = predict(img_path)
37
+ print("The model predicts the image '%s' is a %s, with sigmoid %s" %
38
+ (fname, result[0], result[1]))
39
+ except Exception as e:
40
+ print(f"Error processing {fname}: {e}")
train.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tensorflow as tf
2
+ import os
3
+ import matplotlib.pyplot as plt
4
+ from dotenv import load_dotenv
5
+ from tensorflow.keras.preprocessing.image import ImageDataGenerator
6
+
7
+ load_dotenv()
8
+
9
+ # Hyper Parameter 配置
10
+ BATCH_SIZE = 32
11
+ IMG_SIZE = (224, 224)
12
+ TRAIN_DATASET = os.getenv("TRAIN_DATASET")
13
+ EPOCHS = 8
14
+ OPTIMIZER = 'adam'
15
+ LOSS_FUNC = 'binary_crossentropy'
16
+
17
+ # 数据预处理
18
+ def load_data():
19
+ datagen = ImageDataGenerator(
20
+ validation_split=0.2, # 验证集比例为 20%
21
+ rescale=1./255, # 像素归一化,把 RGB 彩图转为灰度图
22
+ horizontal_flip=True, # 随机水平翻转
23
+ zoom_range=0.2 # 随机缩放,范围在 80%-120%,模拟距离变化
24
+ )
25
+
26
+ train_data = datagen.flow_from_directory(
27
+ directory=TRAIN_DATASET,# 数据位置
28
+ target_size=IMG_SIZE, # 图像尺寸
29
+ batch_size=BATCH_SIZE, # 一次训练样本数量
30
+ class_mode="binary", # 二分类问题
31
+ subset="training", # 训练集
32
+ shuffle=True # 随机打乱数据
33
+ )
34
+
35
+ val_data = datagen.flow_from_directory(
36
+ directory=TRAIN_DATASET,
37
+ target_size=IMG_SIZE,
38
+ batch_size=BATCH_SIZE,
39
+ class_mode="binary",
40
+ subset="validation",
41
+ shuffle=True
42
+ )
43
+
44
+ return train_data, val_data
45
+
46
+ # 构建模型
47
+ def build_model():
48
+ model = tf.keras.Sequential([
49
+ # 第一层卷积:是在输入图像的每一个 3×3 的局部区域上,通过 32 个不同的卷积核,
50
+ # 提取出 32 个特征值,最终形成一张高宽和原图相近、通道数为 32 的特征图。
51
+ # 捕捉初步细节特征,如边缘、纹理等
52
+ tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(*IMG_SIZE, 3)),
53
+ tf.keras.layers.MaxPooling2D(2,2),
54
+
55
+ # 第二层卷积,继续在 3×3 的局部区域上提取 64 个特征图,过程类似
56
+ # 捕捉捕获更复杂的形状和图案
57
+ tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
58
+ tf.keras.layers.MaxPooling2D(2,2),
59
+
60
+ # 第三层卷积
61
+ # 学习更抽象的物体部分或整体形状
62
+ tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
63
+ tf.keras.layers.MaxPooling2D(2,2),
64
+ tf.keras.layers.Flatten(),
65
+ tf.keras.layers.Dense(512, activation='relu'),
66
+ tf.keras.layers.Dense(1, activation='sigmoid')
67
+ ])
68
+
69
+ # 编译模型
70
+ model.compile(optimizer=OPTIMIZER,
71
+ loss=LOSS_FUNC,
72
+ metrics=['accuracy'])
73
+
74
+ return model
75
+
76
+ # 主程序入口
77
+ def main():
78
+ train_data, val_data = load_data()
79
+ model = build_model()
80
+
81
+ # 训练模型并生成训练的历史数据
82
+ history = model.fit(
83
+ train_data,
84
+ epochs = EPOCHS,
85
+ validation_data=val_data
86
+ )
87
+
88
+ # 保存模型
89
+ model.save("cat_dog_model.h5")
90
+
91
+ # 可视化训练过程
92
+ acc = history.history['accuracy']
93
+ loss = history.history['loss']
94
+ val_acc = history.history['val_accuracy']
95
+ val_loss = history.history['val_loss']
96
+ plt.plot(acc, label='Train Accuracy')
97
+ plt.plot(val_acc, label='Validation Accuracy')
98
+ plt.plot(loss, label='Train Loss')
99
+ plt.plot(val_loss, label='Validation Loss')
100
+ plt.legend()
101
+ plt.title('Training Accuracy')
102
+ plt.show()
103
+
104
+ if __name__ == "__main__":
105
+ main()