%% CNN-RNN 通用分类：MNIST 0/1/2二维灰度图试用案例
clear; clc; close all;
fprintf('=== CNN-RNN通用分类试用版 ===\n');
fprintf('最多100条样本；最多两层卷积；隐藏单元不超过64；最多训练30轮\n');
fprintf('试用版开放LSTM和GRU，结果图带试用版水印\n');
fprintf('完整功能与持续更新：www.khsci.com/docs\n\n');

%% 1. 导入数据
% 试用数据为数字0、1、2各30张，X尺寸为90×28×28。
load('mnist_subset.mat', 'X', 'Y');

%% 2. 输入适配与数据划分
options.sampleDimension = 'auto'; % 自动把第一维识别为样本维。
options.sequenceAxis = 2;          % 单张[28,28]图像沿宽度方向逐列读取。
options.rTrain = 0.80;             % 80%为训练+验证数据，20%为最终测试集。
options.validationRatio = 0.15;    % 训练+验证数据中的15%作为验证集。
options.shuffle = true;            % 分层打乱并保持数字类别均衡。
options.seed = 42;                 % 固定划分、初始化和批次顺序。

%% 3. CNN-RNN 网络结构
options.networkType = 'GRU';       % GRU结构较精简，适合演示逐列读图。
options.convChannels = [24, 48];   % 两层CNN提取相邻图像列中的笔画模式。
options.kernelSize = 3;            % 一次观察相邻3列。
options.poolSize = 2;              % 把28列压缩为14个序列位置。
options.rnnHidden = 48;            % GRU隐藏单元数。
options.dropout = 0.20;            % 分类头前随机失活20%。

%% 4. 训练参数
options.solverName = 'adam';       % Adam优化器。
options.maxEpochs = 30;            % 试用版最多30轮，验证集控制提前停止。
options.learnRate = 0.001;         % 初始学习率。
options.batchSize = 16;            % 试用数据仅100张，每批16张保证充分更新。
options.earlyStoppingPatience = 5; % 验证损失连续5次不改善则停止。
options.learnRateSchedule = 'piecewise'; % 分段降低学习率。
options.learnRateDropPeriod = 15;  % 第15轮后降低一次学习率。
options.learnRateDropFactor = 0.5; % 每次衰减为原来的50%。
options.classWeight = 'auto';      % 自动计算类别权重。
options.executionEnvironment = 'auto'; % 自动选择GPU或CPU。

%% 5. 数据处理与图像输出
options.mapflag = 'on';            % on标准化；统计量只来自训练集。
options.figflag = 'on';            % on自动生成五张图，off关闭绘图。
options.showFigures = 'on';        % on运行时弹出图窗。
options.caseName = 'MNIST手写数字';
options.classNames = string(0:2);  % 完整版数据和函数可继续处理0~9十分类。

%% 6. 核心函数入口与输出说明
% X：样本数×高度×宽度灰度图；Y：0/1/2类别；sequenceAxis=2表示逐列读图。
% options：逐项控制分层划分、CNN、GRU、训练、标准化和绘图。
% 试用版最多输入100张图；超限直接停止，不会截断。
% foreData/foreDataTrain：测试/训练预测；net：网络；info包含三集合索引、
% 验证预测、类别得分、各集合指标、训练记录、标准化与输入尺寸记录。
[foreData, foreDataTrain, net, info] = FunClassCNNRNN(X, Y, options);
