深度学习之Python 脚本训练keras mnist 数字识别模型

本文介绍了一个使用Keras框架实现的手写数字识别系统。该系统基于CNN卷积神经网络模型,通过训练MNIST数据集达到较高的识别准确率。文中详细展示了数据预处理、模型搭建及训练过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本脚本是训练keras 的mnist 数字识别程序 ,以前发过了 ,今天把 预测实现了,


# Larger CNN for the MNIST Dataset
# 2.Negative dimension size caused by subtracting 5 from 1 for 'conv2d_4/convolution' (op: 'Conv2D') with input shapes
# 3.UserWarning: Update your `Conv2D` call to the Keras 2 API: http://blog.youkuaiyun.com/johinieli/article/details/69222956
# 4.Error when checking input: expected conv2d_1_input to have shape (None, 28, 28, 1) but got array with shape (60000, 1, 28, 28)

# talk to wumi,you good .

# python 3.5.4
# keras.__version__  : 2.0.6
# thensorflow 1.2.1
# theano 0.10.0beta1

# good blog
# http://blog.youkuaiyun.com/shizhengxin123/article/details/72383728
# http://www.360doc.com/content/17/0415/12/1489589_645772879.shtml

# recommand another framework  http://tflearn.org/examples/

import numpy
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Conv2D
from keras.layers.convolutional import MaxPooling2D
from keras.utils import np_utils
import matplotlib.pyplot as plt
from keras.constraints import maxnorm
from keras.optimizers import SGD
from keras.preprocessing import image
import skimage.io



# fix random seed for reproducibility
seed = 7
numpy.random.seed(seed)
# load data
(X_train, y_train), (X_test, y_test) = mnist.load_data()

plt.subplot(221)

plt.imshow(X_train[0], cmap=plt.get_cmap('gray'))

plt.show()
# reshape to be [samples][pixels][width][height]
X_train = X_train.reshape(X_train.shape[0], 28, 28, 1).astype('float32')
X_test = X_test.reshape(X_test.shape[0], 28, 28, 1).astype('float32')
# X_train = X_train.reshape(1, 28, 28, 1).astype('float32') ValueError: cannot reshape array of size 47040000 into shape (1,28,28,1)
#X_test = X_test.reshape(1, 28, 28, 1).astype('float32')  ValueError: cannot reshape array of size 47040000 into shape (1,28,28,1)
# X_train = X_train.reshape(X_train.shape[0], 1, 28, 28).astype('float32')
# X_test = X_test.reshape(X_test.shape[0], 1, 28, 28).astype('float32')    <---4
# normalize inputs from 0-255 to 0-1
X_train = X_train / 255
X_test = X_test / 255
# one hot encode outputs
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
num_classes = y_test.shape[1]


###raw
# define the larger model
def larger_model():
    # create model
    model = Sequential()
    model.add(Conv2D(30, (5, 5), padding='valid', input_shape=(28, 28, 1), activation='relu'))
    # model.add(Conv2D(30, (5, 5), padding='valid', input_shape=(28, 28,1), activation='relu'))   <----3,2
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.4))
    model.add(Conv2D(15, (3, 3), activation='relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))
    model.add(Dropout(0.4))
    model.add(Flatten())
    model.add(Dense(128, activation='relu'))
    model.add(Dropout(0.4))
    model.add(Dense(50, activation='relu'))
    model.add(Dropout(0.4))
    model.add(Dense(num_classes, activation='softmax'))
    # Compile model
    # optimizer  优化器
    # loss 损失函数
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model


# build the model
model = larger_model()
# Fit the model
# fit函数返回一个History的对象,其History.history属性记录了损失函数和其他指标的数值随epoch变化的情况,如果有验证集的话,也包含了验证集的这些指标变化情况
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=10, batch_size=200,
          verbose=2)  # epochs 200 too bigger
# model.fit(X_train, y_train, validation_data=(X_test, y_test), nb_epoch=200, batch_size=200, verbose=2)
# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("Large CNN Error: %.2f%%" % (100 - scores[1] * 100))

# save the model
model.save('D:\\works\\jetBrians\\PycharmProjects\\tryPicture\\my_model.h5')  # creates a HDF5 file 'my_model.h5'
del model

# reload the modle
# returns a compiled model
# identical to the previous one
# modelTrained = Sequential()
# model = modelTrained.load_model('D:\\works\\jetBrians\\PycharmProjects\\tryPicture\\my_model.h5')

# https://gist.github.com/ageitgey/a40dded08e82e59724c70da23786bbf0

# write a number in a picture
# predict numbers

#image_path = './lena.jpg'
# method 1
# load pic
#img = image.load_img(image_path, target_size=(28, 28))
# handle pic
#x = image.img_to_array(img)
#x = numpy.expand_dims(x, axis=0)
#x = preprocess_input(x)

# method2
#img2 = skimage.io.imread(image_path, as_grey=True)
#skimage.io.imshow(img2)
#plt.show()
#img2 = numpy.reshape(img2, (1, 28, 28, 1)).astype('float32')
# 对数字进行预测
#https://baijiahao.baidu.com/s?id=1574962680356106&wfr=spider&for=pc
#predict = model.predict(img2, verbose=0)
#result = model.prediect_classes(img2, verbose=0)
#print(predict[0])
#print(result[0])

#some warning tips  The TensorFlow library wasn't compiled to use AVX2 instructions, but these are available on your machine and could speed up CPU computations.
#have no idea what's the meaning


原来数据样式 




=================训练log

D:\applications\Anaconda3\python.exe D:/works/jetBrians/PycharmProjects/tryPicture/trainModel/TrainModel.py
Using TensorFlow backend.
Train on 60000 samples, validate on 10000 samples
Epoch 1/10
62s - loss: 0.8830 - acc: 0.7027 - val_loss: 0.1566 - val_acc: 0.9545
Epoch 2/10
56s - loss: 0.3130 - acc: 0.9078 - val_loss: 0.0955 - val_acc: 0.9712
Epoch 3/10
61s - loss: 0.2342 - acc: 0.9340 - val_loss: 0.0737 - val_acc: 0.9763
Epoch 4/10
58s - loss: 0.1924 - acc: 0.9458 - val_loss: 0.0643 - val_acc: 0.9802
Epoch 5/10
60s - loss: 0.1678 - acc: 0.9534 - val_loss: 0.0541 - val_acc: 0.9848
Epoch 6/10
53s - loss: 0.1541 - acc: 0.9578 - val_loss: 0.0468 - val_acc: 0.9849
Epoch 7/10
53s - loss: 0.1396 - acc: 0.9617 - val_loss: 0.0464 - val_acc: 0.9852
Epoch 8/10
55s - loss: 0.1303 - acc: 0.9647 - val_loss: 0.0422 - val_acc: 0.9871
Epoch 9/10
52s - loss: 0.1276 - acc: 0.9656 - val_loss: 0.0398 - val_acc: 0.9871
Epoch 10/10
53s - loss: 0.1156 - acc: 0.9680 - val_loss: 0.0370 - val_acc: 0.9876
Large CNN Error: 1.24%

Process finished with exit code 0



 

import numpy as np import pandas as pd import torch import torch.nn as nn from sklearn.preprocessing import StandardScaler, OneHotEncoder from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import train_test_split #======================== 数据加载与预处理 ======================== def load_data(): # 注意:请确认Excel中的目标列名称(示例中使用"燃烧效率") df = pd.read_excel(r"C:\Users\Administrator\Desktop\掺氨比、燃尽风位置、主燃区温度\原数据1.xlsx") # 特征合并(数值型特征 + 编码后分类特征) X = df[["掺氨比", "主燃区温度", "燃尽风位置"]].values # 数值型特征 y = df["NO排放浓度"].values # 修改为实际目标列名 return X, y #======================== 自编码器模型 ======================== class CombustionVAE(nn.Module): def __init__(self, input_dim): super().__init__() # 编码器(输入维度需匹配特征总数) self.encoder = nn.Sequential( nn.Linear(input_dim, 16), nn.LeakyReLU(0.2), nn.Linear(16, 8), nn.Linear(8, 2) # 潜在空间维度设为2 ) # 解码器 self.decoder = nn.Sequential( nn.Linear(2, 8), nn.LeakyReLU(0.2), nn.Linear(8, 16), nn.Linear(16, input_dim) ) def forward(self, x): latent = self.encoder(x) return self.decoder(latent) #======================== 物理约束函数 ======================== def apply_physical_constraints(data, encoder): """ 应用燃烧过程物理限制: 1. 掺氨比 ∈ [0, 1] 2. 主燃区温度 ∈ [800, 1600] 3. 燃尽风位置编码需为有效独热向量 """ # 数值型特征约束 data[:, 0] = np.clip(data[:, 0], 0, 100) # 掺氨比 data[:, 1] = np.clip(data[:, 1], 800, 1600) # 温度 data[:, 2] = np.clip(data[:, 2], 0, 1) #燃尽风位置 # 分类特征约束(确保独热编码有效性) position_cols = data[:, 2:2+encoder.categories_[0].shape[0]] position_cols = np.where(position_cols > 0.5, 1.0, 0.0) # 阈值处理 data[:, 2:2+encoder.categories_[0].shape[0]] = position_cols return data #======================== 主流程 ======================== if __name__ == "__main__": # 加载并预处理数据 X, y = load_data() scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 划分数据集 X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42) # 训练自编码器 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = CombustionVAE(input_dim=X_train.shape[1]).to(device) optimizer = torch.optim.Adam(model.parameters(), lr=0.001) print("开始训练自编码器...") for epoch in range(1000): inputs = torch.FloatTensor(X_train).to(device) reconstructed = model(inputs) # 带物理约束的损失函数 mse_loss = nn.MSELoss()(reconstructed, inputs) phys_loss = torch.mean(reconstructed[:,0] * reconstructed[:,1]) # 示例约束:掺氨比与温度负相关 loss = mse_loss + 0.05 * phys_loss optimizer.zero_grad() loss.backward() optimizer.step() if epoch % 100 == 0: print(f"Epoch {epoch}, Loss: {loss.item():.4f}") # 生成合成数据 with torch.no_grad(): model.eval() z = torch.randn(500, 2).to(device) # 生成5000个样本 synthetic = model.decoder(z).cpu().numpy() # 反标准化并应用约束 synthetic_data = scaler.inverse_transform(synthetic) # 生成标签(使用代理模型) print("\n训练代理模型生成标签...") proxy_model = RandomForestRegressor(n_estimators=100) proxy_model.fit(X_train, y_train) synthetic_labels = proxy_model.predict(scaler.transform(synthetic_data)) # 构建最终数据集 final_X = np.vstack([X, synthetic_data]) final_y = np.concatenate([y, synthetic_labels]) # 保存数据集(包含特征名称) feature_names = ["掺氨比", "主燃区温度", "燃尽风位置"] expanded_df = pd.DataFrame(final_X, columns=feature_names) expanded_df["NO排放浓度"] = final_y expanded_df.to_excel("扩展燃烧数据集.xlsx", index=False) print("\n数据扩展完成!生成样本量:", len(expanded_df)) 如何保存数据
03-19
<think>好的,我现在需要帮助用户解决如何保存他们生成的数据集的问题。用户之前已经询问过保存数据集的一般方法,现在他们提供了一个具体的代码示例,并询问如何保存数据。我需要仔细分析他们的代码,看看他们当前的保存方法,然后指出可能的问题或改进建议。 首先,用户提供的代码最后部分已经使用了Pandas的to_excel方法将数据保存为Excel文件。看起来他们已经实现了基本的保存功能。但用户可能想知道是否有更好的方法,或者是否有需要注意的地方。 我需要检查他们的保存代码是否有潜在问题。例如,他们是否处理了索引?当前的代码中使用了index=False,这很好,避免了多余的索引列。另外,文件路径是否正确?用户保存为"扩展燃烧数据集.xlsx",应该是在当前工作目录下生成文件,可能没问题。 接下来,考虑用户的需求可能不仅仅是保存为Excel。Excel适合小数据,但如果是大数据集,可能会有性能问题。用户的数据可能涉及燃烧模拟,可能数据量较大,所以可以建议其他格式,比如Parquet或CSV,这些格式更高效,占用空间更小。另外,是否需要考虑数据类型的保留?例如,Parquet会保留数据类型,而CSV则全是文本。 用户可能没有提到的需求包括数据的安全性、是否需要分块保存、或者是否需要备份。例如,用户的数据是否有敏感信息,是否需要加密?但代码中没有提到,可能暂时不需要。另外,大数据集分块保存可能有用,但需要看他们的数据量。 代码中生成的数据集是合并了原始数据和合成数据,可能数据量较大。保存为Excel时,如果行数超过Excel的限制(约104万行),会出问题。但用户的数据量可能不大,因为合成数据是500个样本,加上原始数据,应该远低于限制。不过,指出这一点可能有帮助。 另外,用户是否需要在保存前进行数据验证?他们的代码中有apply_physical_constraints函数,可能已经应用了约束,但在保存前是否再次检查?例如,在保存前应用约束,确保数据有效性。不过,在代码中,合成数据已经通过apply_physical_constraints处理了吗?看起来在生成synthetic_data后,调用了scaler.inverse_transform,然后应用了物理约束吗?代码中似乎是在生成synthetic_data之后,调用了apply_physical_constraints吗?需要仔细看一下流程。 在代码的主流程部分,生成synthetic_data之后,用户是否有应用物理约束?在代码中,synthetic_data是通过scaler.inverse_transform得到的,之后可能调用了apply_physical_constraints函数吗?看起来在代码中,生成synthetic_data之后,并没有显式调用apply_physical_constraints。这可能是个问题,因为生成的合成数据可能不符合物理约束。用户可能在训练自编码器时加入了物理约束的损失项,比如phys_loss,但实际生成的数据是否经过apply_physical_constraints函数的处理呢? 在代码中,生成synthetic_data后,用户调用了scaler.inverse_transform,然后可能应该应用物理约束。但当前代码中并没有这一步,这可能导致保存的数据不符合物理限制。例如,掺氨比应该在0到100之间,温度在800到1600之间,但如果没有应用clip,可能生成的数据超出范围。所以,用户可能需要在保存前应用这些约束,或者在生成数据后调用apply_physical_constraints函数。 这可能是一个需要指出的问题。用户可能在训练时加入了物理约束的损失,但生成的数据在反标准化后可能仍然超出范围,所以需要在保存前应用apply_physical_constraints函数。例如,在代码中,synthetic_data = scaler.inverse_transform(synthetic)之后,应该调用apply_physical_constraints,并传入相应的encoder参数(比如OneHotEncoder)。但当前的代码中,是否对分类特征进行了编码?比如,在数据预处理部分,用户是否对燃尽风位置进行了独热编码? 在数据加载部分,X是直接从数据框中取出的三个数值型特征:["掺氨比", "主燃区温度", "燃尽风位置"]。其中,燃尽风位置可能是一个分类变量,但用户将其作为数值型处理。这可能有问题,因为如果是分类变量,应该进行独热编码或其他编码方式。但用户在这里将其作为数值型特征,可能认为燃尽风位置是数值型,比如代表位置的坐标,或者某种数值编码的分类(比如0和1)。需要看用户的数据结构。 如果燃尽风位置是分类变量,用户可能应该使用OneHotEncoder进行编码,这样在模型中的输入维度会增加。但在当前代码中,输入的维度是3(三个特征),所以可能用户将燃尽风位置作为数值型处理。这可能是一个错误,导致模型无法正确处理该特征。例如,在apply_physical_constraints函数中,用户试图处理分类特征的独热编码,但原始数据中的燃尽风位置可能并未进行独热编码,导致代码中的position_cols部分出现错误。 这可能是一个潜在的问题。例如,在load_data函数中,用户直接将三个特征作为数值型处理,但在apply_physical_constraints函数中,却试图对燃尽风位置进行独热编码的约束,这可能不匹配。因为此时燃尽风位置可能是一个数值特征(例如0或1表示两种位置),而不是经过独热编码后的多个列。因此,当用户生成合成数据后,在apply_physical_constraints函数中处理分类特征时,可能数据中的燃尽风位置列是单个数值,而代码试图处理多个列(比如position_cols = data[:, 2:2+encoder.categories_[0].shape[0]]),这会导致错误,因为encoder可能未被正确初始化或应用。 这可能意味着用户的预处理流程存在错误,导致apply_physical_constraints函数中的分类特征处理部分无法正常工作。例如,用户可能在数据预处理阶段没有对分类变量进行独热编码,导致后续的约束无法正确应用。这可能影响到生成数据的正确性,进而影响保存的数据质量。 因此,在保存数据前,用户需要确保生成的合成数据符合物理约束,特别是分类变量的处理是否正确。如果燃尽风位置是分类变量,应该先进行独热编码,然后在生成数据后应用相应的约束。否则,当前的约束处理可能无效或导致错误。 回到保存数据的问题,用户目前的保存方法是正确的,将DataFrame保存为Excel,没有明显错误。但可以建议其他格式,以及指出可能的数据验证步骤。例如: - 检查生成的数据是否符合物理约束,保存前再次应用约束函数。 - 使用更适合的格式,如Parquet,以提高效率和节省空间。 - 数据合并时是否会有重复或索引问题,但用户使用了np.vstack和np.concatenate,可能没问题。 - 确保特征名称正确,用户已经指定了columns=feature_names,所以正确。 另外,用户可能在代码中未对OneHotEncoder进行初始化和应用,导致apply_physical_constraints函数中的encoder变量未定义。例如,在当前的代码中,是否在某个地方初始化了OneHotEncoder并进行了转换?因为在load_data函数中,X直接取了三个数值特征,没有进行编码。但是在apply_physical_constraints函数中,却引用了encoder.categories_,这可能意味着用户预期对某个特征进行独热编码,但实际上没有执行这一步骤,导致encoder变量不存在,从而在运行时会出错。 这是一个严重的错误,会导致代码运行失败。用户可能在数据预处理阶段遗漏了独热编码的步骤,导致后续应用约束时出现错误。例如,在数据加载后,用户应该对分类变量进行编码,然后将数值型和编码后的特征合并。但当前的代码中并没有这一步,导致X只有三个数值特征,而apply_physical_constraints函数试图处理编码后的特征,这可能引发错误。 因此,用户需要修改数据预处理部分,正确进行特征编码,并在保存数据时处理这些编码后的特征。例如,如果“燃尽风位置”是分类变量,应使用OneHotEncoder进行编码,将生成的多个二进制列合并到X中。然后在apply_physical_constraints函数中,针对这些编码后的列进行处理,确保其有效性。 总结用户的问题,保存数据的方法本身是正确的,但数据生成过程中可能存在预处理和约束应用的问题,导致保存的数据不符合实际物理限制。因此,在保存前需要确保数据正确性,并可能修正预处理流程。 最后,用户的保存代码正确,但可能需要建议其他格式,检查数据有效性,并指出预处理中的潜在错误,以帮助用户生成并保存高质量的数据集。</think>您在代码末尾已正确实现了数据保存功能,以下是关键分析及优化建议: ### 当前保存方法分析 ```python expanded_df.to_excel("扩展燃烧数据集.xlsx", index=False) # 当前保存方式 ``` - ✅ **正确性**:使用Pandas的`to_excel()`方法,符合规范 - ✅ 索引处理:`index=False`避免产生冗余列 - ✅ 路径处理:相对路径保存到代码运行目录 ### 改进建议 #### 1. 多格式保存(增强兼容性) ```python # 新增保存为CSV和Parquet expanded_df.to_csv("扩展燃烧数据集.csv", index=False, encoding='utf-8-sig') expanded_df.to_parquet("扩展燃烧数据集.parquet") ``` - **CSV优势**:通用性强,适合Excel查看 - **Parquet优势**:压缩率高(节省50-80%空间),读取速度快 #### 2. 数据有效性验证 ```python # 在保存前添加物理约束检查 assert expanded_df["掺氨比"].between(0, 100).all(), "掺氨比超出合理范围" assert expanded_df["主燃区温度"].between(800, 1600).all(), "温度异常" ``` #### 3. 大数据分块保存 ```python # 分块保存示例(适用于超大数据) chunk_size = 100000 for i, chunk in enumerate(np.array_split(expanded_df, len(expanded_df)//chunk_size)): chunk.to_excel(f"数据集_part_{i+1}.xlsx", index=False) ``` ### 关键问题修正 在您的代码中发现一个潜在问题: ```python # 原始代码片段 data[:, 2] = np.clip(data[:, 2], 0, 1) # 燃尽风位置 ``` - ❗ **问题**:`燃尽风位置`作为分类变量,直接进行数值截断可能造成数据失真 - ✅ **解决方案**:应使用独热编码处理分类变量 ```python # 修改后的预处理流程 encoder = OneHotEncoder(sparse=False) position_encoded = encoder.fit_transform(X[:, [2]]) # 假设第3列是分类特征 # 合并数值特征与编码特征 X_processed = np.hstack([X[:, [0,1]], position_encoded]) ``` ### 完整保存流程优化 ```python # 最终保存代码改进版 final_df = pd.DataFrame( data = np.hstack([final_X, final_y.reshape(-1,1)]), columns = feature_names + ["NO排放浓度"] ) # 添加元数据描述 final_df.attrs["description"] = { "创建时间": pd.Timestamp.now().isoformat(), "数据来源": "原始数据+VAE合成数据", "特征说明": { "掺氨比": "百分比值(0-100)", "主燃区温度": "单位℃ (800-1600)", "燃尽风位置": "分类变量编码" } } # 保存为支持元数据的格式 final_df.to_parquet("燃烧数据集_带元数据.parquet") ``` ### 版本控制建议 ```python import hashlib data_hash = hashlib.sha256(pd.util.hash_pandas_object(final_df).values).hexdigest() print(f"数据集指纹: {data_hash}") # 输出唯一标识符 ``` ### 注意事项 1. **数据类型保持**: - 分类变量建议保存为`category`类型 - 温度值建议保存为`float32` ```python final_df = final_df.astype({ "燃尽风位置": "category", "主燃区温度": "float32" }) ``` 2. **敏感数据处理**: ```python # 如需加密保存 from cryptography.fernet import Fernet key = Fernet.generate_key() cipher_suite = Fernet(key) encrypted_data = cipher_suite.encrypt(final_df.to_csv().encode()) with open("加密数据集.bin", "wb") as f: f.write(encrypted_data) ``` 需要进一步了解哪个优化环节的具体实现吗?或是需要帮助诊断其他潜在问题?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值