initial commit
Browse files- .cspell.json +6 -0
- .env.example +3 -0
- .gitignore +3 -0
- LICENSE +121 -0
- README.md +68 -0
- environment.yml +0 -0
- test.py +40 -0
- 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()
|