[{"data":1,"prerenderedAt":585},["ShallowReactive",2],{"content-query-kS0J2ReJxl":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"cover":11,"type":12,"body":13,"_type":579,"_id":580,"_source":581,"_file":582,"_stem":583,"_extension":584},"/technology-blogs/zh/1050","zh",false,"","时装连连看，基于MindSpore实现FashionMNIST图像分类","使用训练模型对图片数据进行分类预测","2022-02-23","https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2022/03/02/bcca5cd8eb304ebb9a130ba17377c6a6.png","technology-blogs",{"type":14,"children":15,"toc":564},"root",[16,24,46,51,76,83,90,128,133,141,147,161,171,176,185,190,198,203,211,216,224,241,247,260,268,273,280,295,300,308,314,319,327,332,339,345,358,363,371,377,390,398,404,409,417,422,430,459,467,472,480,493,501,506,514,527,532,538,543,551,556],{"type":17,"tag":18,"props":19,"children":21},"element","h1",{"id":20},"时装连连看基于mindspore实现fashionmnist图像分类",[22],{"type":23,"value":8},"text",{"type":17,"tag":25,"props":26,"children":27},"p",{},[28,39,41],{"type":17,"tag":29,"props":30,"children":31},"strong",{},[32,34],{"type":23,"value":33},"作者：",{"type":17,"tag":29,"props":35,"children":36},{},[37],{"type":23,"value":38},"Kaierlong",{"type":23,"value":40}," ｜",{"type":17,"tag":29,"props":42,"children":43},{},[44],{"type":23,"value":45},"来源：华为云 MindSpore论坛",{"type":17,"tag":25,"props":47,"children":48},{},[49],{"type":23,"value":50},"本文主要内容：",{"type":17,"tag":52,"props":53,"children":54},"ul",{},[55,61,66,71],{"type":17,"tag":56,"props":57,"children":58},"li",{},[59],{"type":23,"value":60},"数据准备",{"type":17,"tag":56,"props":62,"children":63},{},[64],{"type":23,"value":65},"模型构建",{"type":17,"tag":56,"props":67,"children":68},{},[69],{"type":23,"value":70},"模型训练",{"type":17,"tag":56,"props":72,"children":73},{},[74],{"type":23,"value":75},"模型验证",{"type":17,"tag":77,"props":78,"children":80},"h2",{"id":79},"_1-数据准备",[81],{"type":23,"value":82},"1. 数据准备",{"type":17,"tag":84,"props":85,"children":87},"h3",{"id":86},"_11-数据简介",[88],{"type":23,"value":89},"1.1 数据简介",{"type":17,"tag":25,"props":91,"children":92},{},[93,100,102,111,113,119,121,126],{"type":17,"tag":94,"props":95,"children":97},"code",{"className":96},[],[98],{"type":23,"value":99},"Fashion-MNIST",{"type":23,"value":101},"是一个替代",{"type":17,"tag":103,"props":104,"children":108},"a",{"href":105,"rel":106},"https://bbs.huaweicloud.com/forum/forum.php?mod=viewthread&tid=179255#",[107],"nofollow",[109],{"type":23,"value":110},"MNIST手写数字集",{"type":23,"value":112},"的图像数据集。 它是由Zalando（一家德国的时尚科技公司）旗下的",{"type":17,"tag":103,"props":114,"children":116},{"href":105,"rel":115},[107],[117],{"type":23,"value":118},"研究部门",{"type":23,"value":120},"提供。其涵盖了来自10种类别的共7万个不同商品的正面图片。Fashion-MNIST的大小、格式和训练集/测试集划分与原始的MNIST完全一致。60000/10000的训练测试数据划分，28x28的灰度图片。你可以直接用它来测试你的机器学习和深度学习算法性能，且",{"type":17,"tag":29,"props":122,"children":123},{},[124],{"type":23,"value":125},"不需要",{"type":23,"value":127},"改动任何的代码。",{"type":17,"tag":25,"props":129,"children":130},{},[131],{"type":23,"value":132},"这个数据集的样子大致如下（每个类别占三行）：",{"type":17,"tag":25,"props":134,"children":135},{},[136],{"type":17,"tag":137,"props":138,"children":140},"img",{"alt":7,"src":139},"https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202202/09/164643olpgzfkbgk7okokh.png",[],{"type":17,"tag":84,"props":142,"children":144},{"id":143},"_12-下载数据",[145],{"type":23,"value":146},"1.2 下载数据",{"type":17,"tag":25,"props":148,"children":149},{},[150,152,159],{"type":23,"value":151},"数据官方仓库为",{"type":17,"tag":103,"props":153,"children":156},{"href":154,"rel":155},"https://gitee.com/mirrors/Fashion-MNIST",[107],[157],{"type":23,"value":158},"https://github.com/zalandoresearch/fashion-mnist",{"type":23,"value":160},"，但是下载速度较慢。",{"type":17,"tag":25,"props":162,"children":163},{},[164,166],{"type":23,"value":165},"这里从gitee备份镜像下载，地址为",{"type":17,"tag":103,"props":167,"children":169},{"href":154,"rel":168},[107],[170],{"type":23,"value":154},{"type":17,"tag":25,"props":172,"children":173},{},[174],{"type":23,"value":175},"克隆数据仓库",{"type":17,"tag":177,"props":178,"children":180},"pre",{"code":179},"git clone https://gitee.com/mirrors/Fashion-MNIST.git\n",[181],{"type":17,"tag":94,"props":182,"children":183},{"__ignoreMap":7},[184],{"type":23,"value":179},{"type":17,"tag":25,"props":186,"children":187},{},[188],{"type":23,"value":189},"创建数据目录",{"type":17,"tag":177,"props":191,"children":193},{"code":192},"mkdir data && cd data\n",[194],{"type":17,"tag":94,"props":195,"children":196},{"__ignoreMap":7},[197],{"type":23,"value":192},{"type":17,"tag":25,"props":199,"children":200},{},[201],{"type":23,"value":202},"复制数据",{"type":17,"tag":177,"props":204,"children":206},{"code":205},"cp ../Fashion-MNIST/data/fashion/* ./\n",[207],{"type":17,"tag":94,"props":208,"children":209},{"__ignoreMap":7},[210],{"type":23,"value":205},{"type":17,"tag":25,"props":212,"children":213},{},[214],{"type":23,"value":215},"校验数据",{"type":17,"tag":177,"props":217,"children":219},{"code":218},"md5sum *\n",[220],{"type":17,"tag":94,"props":221,"children":222},{"__ignoreMap":7},[223],{"type":23,"value":218},{"type":17,"tag":225,"props":226,"children":227},"blockquote",{},[228,233],{"type":17,"tag":25,"props":229,"children":230},{},[231],{"type":23,"value":232},"校验结果如下所示",{"type":17,"tag":177,"props":234,"children":236},{"code":235},"bef4ecab320f06d8554ea6380940ec79  t10k-images-idx3-ubyte.gz\nbb300cfdad3c16e7a12a480ee83cd310  t10k-labels-idx1-ubyte.gz\n8d4fb7e6c68d591d4c3dfef9ec88bf0d  train-images-idx3-ubyte.gz\n25c81989df183df01b3e8a0aad5dffbe  train-labels-idx1-ubyte.gz\n",[237],{"type":17,"tag":94,"props":238,"children":239},{"__ignoreMap":7},[240],{"type":23,"value":235},{"type":17,"tag":84,"props":242,"children":244},{"id":243},"_13-解压数据",[245],{"type":23,"value":246},"1.3 解压数据",{"type":17,"tag":25,"props":248,"children":249},{},[250,252,258],{"type":23,"value":251},"解压缩",{"type":17,"tag":94,"props":253,"children":255},{"className":254},[],[256],{"type":23,"value":257},"gz",{"type":23,"value":259},"数据",{"type":17,"tag":177,"props":261,"children":263},{"code":262},"gunzip *\n",[264],{"type":17,"tag":94,"props":265,"children":266},{"__ignoreMap":7},[267],{"type":23,"value":262},{"type":17,"tag":25,"props":269,"children":270},{},[271],{"type":23,"value":272},"校验解压后数据",{"type":17,"tag":177,"props":274,"children":275},{"code":218},[276],{"type":17,"tag":94,"props":277,"children":278},{"__ignoreMap":7},[279],{"type":23,"value":218},{"type":17,"tag":225,"props":281,"children":282},{},[283,287],{"type":17,"tag":25,"props":284,"children":285},{},[286],{"type":23,"value":232},{"type":17,"tag":177,"props":288,"children":290},{"code":289},"8181f5470baa50b63fa0f6fddb340f0a  t10k-images-idx3-ubyte\n15d484375f8d13e6eb1aabb0c3f46965  t10k-labels-idx1-ubyte\nf4a8712d7a061bf5bd6d2ca38dc4d50a  train-images-idx3-ubyte\n9018921c3c673c538a1fc5bad174d6f9  train-labels-idx1-ubyte\n",[291],{"type":17,"tag":94,"props":292,"children":293},{"__ignoreMap":7},[294],{"type":23,"value":289},{"type":17,"tag":25,"props":296,"children":297},{},[298],{"type":23,"value":299},"最终数据目录结构如下：",{"type":17,"tag":177,"props":301,"children":303},{"code":302},"data/\n├── t10k-images-idx3-ubyte\n├── t10k-labels-idx1-ubyte\n├── train-images-idx3-ubyte\n└── train-labels-idx1-ubyte\n",[304],{"type":17,"tag":94,"props":305,"children":306},{"__ignoreMap":7},[307],{"type":23,"value":302},{"type":17,"tag":84,"props":309,"children":311},{"id":310},"_14-初探数据",[312],{"type":23,"value":313},"1.4 初探数据",{"type":17,"tag":25,"props":315,"children":316},{},[317],{"type":23,"value":318},"使用如下代码，可以可视化查看部分数据集。",{"type":17,"tag":177,"props":320,"children":322},{"code":321},"import matplotlib.pyplot as plt\nimport mindspore.dataset as ds\n\n\nif __name__ == \"__main__\":\n    fashion_mnist_dataset_dir = \"./data/\"\n    fashion_mnist_dataset = ds.FashionMnistDataset(dataset_dir=fashion_mnist_dataset_dir, num_samples=3)\n    fashion_mnist_it = fashion_mnist_dataset.create_dict_iterator()\n    data = next(fashion_mnist_it)\n\n    plt.imshow(data['image'].asnumpy().reshape(28, 28), cmap='gray')\n    plt.title(data['label'].asnumpy(), fontsize=20)\n    plt.show()\n",[323],{"type":17,"tag":94,"props":324,"children":325},{"__ignoreMap":7},[326],{"type":23,"value":321},{"type":17,"tag":25,"props":328,"children":329},{},[330],{"type":23,"value":331},"下图为标签7运动鞋（Sneaker）样本的可视化图片。",{"type":17,"tag":25,"props":333,"children":334},{},[335],{"type":17,"tag":137,"props":336,"children":338},{"alt":7,"src":337},"https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202202/09/164708qon0undluslnbrle.png",[],{"type":17,"tag":84,"props":340,"children":342},{"id":341},"_15-数据处理",[343],{"type":23,"value":344},"1.5 数据处理",{"type":17,"tag":225,"props":346,"children":347},{},[348,353],{"type":17,"tag":25,"props":349,"children":350},{},[351],{"type":23,"value":352},"本来笔者想实现mindrecord版本的fashion-minst读取，结果发现官方已经做了支持。",{"type":17,"tag":25,"props":354,"children":355},{},[356],{"type":23,"value":357},"所以这里借用官方的接口和相关数据处理方法。",{"type":17,"tag":25,"props":359,"children":360},{},[361],{"type":23,"value":362},"代码和所需要的引入的包库如下所示。",{"type":17,"tag":177,"props":364,"children":366},{"code":365},"import mindspore.dataset as ds\nimport mindspore.dataset.transforms.c_transforms as C\nimport mindspore.dataset.vision.c_transforms as CV\nfrom mindspore.dataset.vision import Inter\nfrom mindspore import dtype as mstype\n\n\ndef create_dataset(data_path, usage=\"train\", batch_size=32, repeat_size=1, num_parallel_workers=1):\n    # 定义数据集\n    fashion_mnist_ds = ds.FashionMnistDataset(data_path, usage=usage)\n    resize_height, resize_width = 28, 28\n    rescale = 1.0 / 255.0\n    shift = 0.0\n    rescale_nml = 1 / 0.3081\n    shift_nml = -1 * 0.1307 / 0.3081\n\n    # 定义所需要操作的map映射\n    resize_op = CV.Resize((resize_height, resize_width), interpolation=Inter.LINEAR)\n    rescale_nml_op = CV.Rescale(rescale_nml, shift_nml)\n    rescale_op = CV.Rescale(rescale, shift)\n    hwc2chw_op = CV.HWC2CHW()\n    type_cast_op = C.TypeCast(mstype.int32)\n\n    # 使用map映射函数，将数据操作应用到数据集\n    fashion_mnist_ds = fashion_mnist_ds.map(\n        operations=type_cast_op, input_columns=\"label\", num_parallel_workers=num_parallel_workers)\n    fashion_mnist_ds = fashion_mnist_ds.map(\n        operations=[resize_op, rescale_op, rescale_nml_op, hwc2chw_op],\n        input_columns=\"image\", num_parallel_workers=num_parallel_workers)\n\n    # 进行shuffle、batch、repeat操作\n    buffer_size = 10000\n    fashion_mnist_ds = fashion_mnist_ds.shuffle(buffer_size=buffer_size)\n    fashion_mnist_ds = fashion_mnist_ds.batch(batch_size, drop_remainder=True)\n    fashion_mnist_ds = fashion_mnist_ds.repeat(count=repeat_size)\n\n    return fashion_mnist_ds\n",[367],{"type":17,"tag":94,"props":368,"children":369},{"__ignoreMap":7},[370],{"type":23,"value":365},{"type":17,"tag":77,"props":372,"children":374},{"id":373},"_2-模型构建",[375],{"type":23,"value":376},"2. 模型构建",{"type":17,"tag":25,"props":378,"children":379},{},[380,382,388],{"type":23,"value":381},"这里在官方Mnist教程中",{"type":17,"tag":94,"props":383,"children":385},{"className":384},[],[386],{"type":23,"value":387},"LeNet5",{"type":23,"value":389},"网络的基础上做适当修改。具体代码如下所示。",{"type":17,"tag":177,"props":391,"children":393},{"code":392},"import mindspore.nn as nn\nfrom mindspore.common.initializer import Normal\n\n\nclass LeNet5(nn.Cell):\n    \"\"\"\n    Lenet网络结构\n    \"\"\"\n    def __init__(self, num_class=10, num_channel=1):\n        super(LeNet5, self).__init__()\n        # 定义所需要的运算\n        self.conv1 = nn.Conv2d(num_channel, 6, 5, pad_mode='valid')\n        self.conv2 = nn.Conv2d(6, 16, 5, pad_mode='valid')\n        self.fc1 = nn.Dense(16 * 4 * 4, 256, weight_init=Normal(0.02))\n        self.fc2 = nn.Dense(256, 128, weight_init=Normal(0.02))\n        self.fc3 = nn.Dense(128, num_class, weight_init=Normal(0.02))\n        self.relu = nn.ReLU()\n        self.max_pool2d = nn.MaxPool2d(kernel_size=2, stride=2)\n        self.flatten = nn.Flatten()\n\n    def construct(self, x):\n        # 使用定义好的运算构建前向网络\n        x = self.conv1(x)\n        x = self.relu(x)\n        x = self.max_pool2d(x)\n        x = self.conv2(x)\n        x = self.relu(x)\n        x = self.max_pool2d(x)\n        x = self.flatten(x)\n        x = self.fc1(x)\n        x = self.relu(x)\n        x = self.fc2(x)\n        x = self.relu(x)\n        x = self.fc3(x)\n        return x\n",[394],{"type":17,"tag":94,"props":395,"children":396},{"__ignoreMap":7},[397],{"type":23,"value":392},{"type":17,"tag":77,"props":399,"children":401},{"id":400},"_3-模型训练",[402],{"type":23,"value":403},"3. 模型训练",{"type":17,"tag":25,"props":405,"children":406},{},[407],{"type":23,"value":408},"模型训练主要是为了找到理想的网络参数，需要定义损失函数和优化器。相应部分的代码如下所示。",{"type":17,"tag":177,"props":410,"children":412},{"code":411},"# 实例化网络\nnet = LeNet5()\n# 定义损失函数\nnet_loss = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')\n# 定义优化器\nnet_opt = nn.Momentum(net.trainable_params(), learning_rate=0.01, momentum=0.9)\n",[413],{"type":17,"tag":94,"props":414,"children":415},{"__ignoreMap":7},[416],{"type":23,"value":411},{"type":17,"tag":25,"props":418,"children":419},{},[420],{"type":23,"value":421},"训练后的模型需要保存下载，进行下一步模型验证或Fine-tune微调相关工作。模型保存部分的代码如下所示。",{"type":17,"tag":177,"props":423,"children":425},{"code":424},"# 设置模型保存参数\nconfig_ck = CheckpointConfig(save_checkpoint_steps=100, keep_checkpoint_max=10)\n# 应用模型保存参数\nckpt_cb = ModelCheckpoint(prefix=\"lenet_ckpt\", config=config_ck)\n",[426],{"type":17,"tag":94,"props":427,"children":428},{"__ignoreMap":7},[429],{"type":23,"value":424},{"type":17,"tag":25,"props":431,"children":432},{},[433,435,441,443,449,451,457],{"type":23,"value":434},"通过MindSpore提供的",{"type":17,"tag":94,"props":436,"children":438},{"className":437},[],[439],{"type":23,"value":440},"model.train",{"type":23,"value":442},"接口可以方便地进行网络的训练，",{"type":17,"tag":94,"props":444,"children":446},{"className":445},[],[447],{"type":23,"value":448},"LossMonitor",{"type":23,"value":450},"可以监控训练过程中",{"type":17,"tag":94,"props":452,"children":454},{"className":453},[],[455],{"type":23,"value":456},"loss",{"type":23,"value":458},"值的变化。",{"type":17,"tag":177,"props":460,"children":462},{"code":461},"def train_net(model, epoch_size, data_path, batch_size, repeat_size, ckpt_cb, sink_mode):\n    \"\"\"定义训练的方法\"\"\"\n    # 加载训练数据集\n    ds_train = create_dataset(data_path, usage=\"train\", batch_size=batch_size, repeat_size=repeat_size)\n    model.train(epoch_size, ds_train, callbacks=[ckpt_cb, LossMonitor(125)], dataset_sink_mode=sink_mode)\n",[463],{"type":17,"tag":94,"props":464,"children":465},{"__ignoreMap":7},[466],{"type":23,"value":461},{"type":17,"tag":25,"props":468,"children":469},{},[470],{"type":23,"value":471},"通过模型运行测试数据集得到的结果，验证模型的泛化能力。",{"type":17,"tag":177,"props":473,"children":475},{"code":474},"def test_net(model, data_path):\n    \"\"\"定义验证的方法\"\"\"\n    ds_eval = create_dataset(data_path, usage=\"test\")\n    acc = model.eval(ds_eval, dataset_sink_mode=False)\n    print(\"acc: {}\".format(acc), flush=True)\n",[476],{"type":17,"tag":94,"props":477,"children":478},{"__ignoreMap":7},[479],{"type":23,"value":474},{"type":17,"tag":25,"props":481,"children":482},{},[483,485,491],{"type":23,"value":484},"以上代码为拆分开的代码，整体运行代码见",{"type":17,"tag":94,"props":486,"children":488},{"className":487},[],[489],{"type":23,"value":490},"main.py",{"type":23,"value":492},"文件。可使用如下命令训练模型：",{"type":17,"tag":177,"props":494,"children":496},{"code":495},"python3 main.py --data_path=./data --device_target=CPU\n",[497],{"type":17,"tag":94,"props":498,"children":499},{"__ignoreMap":7},[500],{"type":23,"value":495},{"type":17,"tag":25,"props":502,"children":503},{},[504],{"type":23,"value":505},"训练过程中会打印loss值，类似下图。loss值会波动，但总体来说loss值会逐步减小，精度逐步提高。每个人运行的loss值有一定随机性，不一定完全相同。 训练过程中loss打印示例如下：",{"type":17,"tag":177,"props":507,"children":509},{"code":508},"epoch: 1 step: 125, loss is 2.295269250869751\nepoch: 1 step: 250, loss is 2.3060524463653564\nepoch: 1 step: 375, loss is 1.4239269495010376\nepoch: 1 step: 500, loss is 0.6873521208763123\nepoch: 1 step: 625, loss is 0.8742141723632812\n......\nepoch: 5 step: 1375, loss is 0.5237604975700378\nepoch: 5 step: 1500, loss is 0.242930606007576\nepoch: 5 step: 1625, loss is 0.37006133794784546\nepoch: 5 step: 1750, loss is 0.46649742126464844\nepoch: 5 step: 1875, loss is 0.1670462042093277\nacc: {'Accuracy': 0.8619791666666666}\n",[510],{"type":17,"tag":94,"props":511,"children":512},{"__ignoreMap":7},[513],{"type":23,"value":508},{"type":17,"tag":25,"props":515,"children":516},{},[517,519,525],{"type":23,"value":518},"可以在打印信息中看出模型精度数据，示例中精度数据达到86.2%，模型质量良好。随着网络迭代次数",{"type":17,"tag":94,"props":520,"children":522},{"className":521},[],[523],{"type":23,"value":524},"train_epoch",{"type":23,"value":526},"增加，模型精度会进一步提高。",{"type":17,"tag":25,"props":528,"children":529},{},[530],{"type":23,"value":531},"读者也可以尝试使用不同的网络结构来优化模型，以提高模型精度。",{"type":17,"tag":77,"props":533,"children":535},{"id":534},"_4-模型验证",[536],{"type":23,"value":537},"4. 模型验证",{"type":17,"tag":25,"props":539,"children":540},{},[541],{"type":23,"value":542},"使用如下代码加载训练的模型，并对单个图片数据进行分类预测。",{"type":17,"tag":177,"props":544,"children":546},{"code":545},"import numpy as np\n\nfrom mindspore import load_checkpoint, load_param_into_net\n\nfrom mindspore import Model\nfrom mindspore import Tensor\n\n# create_dataset definition\n# LeNet5 definition\n\ndef predict():\n    net = LeNet5()\n\n    # 加载已经保存的用于测试的模型\n    param_dict = load_checkpoint(\"lenet_ckpt-5_1875.ckpt\")\n    # 加载参数到网络中\n    load_param_into_net(net, param_dict)\n\n    # 定义测试数据集，batch_size设置为1，则取出一张图片\n    fashion_minst_path = \"./data\"\n    ds_test = create_dataset(data_path=fashion_minst_path, usage=\"test\", batch_size=1).create_dict_iterator()\n\n    for i in range(1000):\n        data = next(ds_test)\n\n    data = next(ds_test)\n    # images为测试图片，labels为测试图片的实际分类\n    images = data[\"image\"].asnumpy()\n    labels = data[\"label\"].asnumpy()\n\n    model = Model(net)\n    # 使用函数model.predict预测image对应分类\n    output = model.predict(Tensor(data['image']))\n    predicted = np.argmax(output.asnumpy(), axis=1)\n\n    # 输出预测分类与实际分类\n    print(f'Predicted: \"{predicted[0]}\", Actual: \"{labels[0]}\"')\n\n\nif __name__ == \"__main__\":\n    predict()\n",[547],{"type":17,"tag":94,"props":548,"children":549},{"__ignoreMap":7},[550],{"type":23,"value":545},{"type":17,"tag":25,"props":552,"children":553},{},[554],{"type":23,"value":555},"示例输出如下内容：",{"type":17,"tag":177,"props":557,"children":559},{"code":558},"Predicted: \"5\", Actual: \"5\"\n",[560],{"type":17,"tag":94,"props":561,"children":562},{"__ignoreMap":7},[563],{"type":23,"value":558},{"title":7,"searchDepth":565,"depth":565,"links":566},4,[567,576,577,578],{"id":79,"depth":568,"text":82,"children":569},2,[570,572,573,574,575],{"id":86,"depth":571,"text":89},3,{"id":143,"depth":571,"text":146},{"id":243,"depth":571,"text":246},{"id":310,"depth":571,"text":313},{"id":341,"depth":571,"text":344},{"id":373,"depth":568,"text":376},{"id":400,"depth":568,"text":403},{"id":534,"depth":568,"text":537},"markdown","content:technology-blogs:zh:1050.md","content","technology-blogs/zh/1050.md","technology-blogs/zh/1050","md",1776506111626]