如何将 Keras .h5 导出为 tensorflow .pb?

2025-02-20 09:23:00
admin
原创
34
摘要:问题描述:我已经使用新数据集对初始模型进行了微调,并将其在 Keras 中保存为“.h5”模型。现在我的目标是在仅接受“.pb”扩展名的 android Tensorflow 上运行我的模型。问题是 Keras 或 tensorflow 中是否有任何库可以进行这种转换?到目前为止,我已经看过这篇文章: htt...

问题描述:

我已经使用新数据集对初始模型进行了微调,并将其在 Keras 中保存为“.h5”模型。现在我的目标是在仅接受“.pb”扩展名的 android Tensorflow 上运行我的模型。问题是 Keras 或 tensorflow 中是否有任何库可以进行这种转换?到目前为止,我已经看过这篇文章: https://blog.keras.io/keras-as-a-simplified-interface-to-tensorflow-tutorial.html,但还无法弄清楚。


解决方案 1:

Keras 本身不包含任何将 TensorFlow 图导出为协议缓冲区文件的方法,但您可以使用常规 TensorFlow 实用程序来执行此操作。这里有一篇博客文章解释了如何使用freeze_graph.pyTensorFlow 中包含的实用程序脚本来执行此操作,这是“典型”的方法。

但是,我个人觉得必须先建立检查点然后运行外部脚本来获取模型很麻烦,我更喜欢用自己的 Python 代码来执行此操作,因此我使用了这样的函数:

def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
    """
    Freezes the state of a session into a pruned computation graph.

    Creates a new computation graph where variable nodes are replaced by
    constants taking their current value in the session. The new graph will be
    pruned so subgraphs that are not necessary to compute the requested
    outputs are removed.
    @param session The TensorFlow session to be frozen.
    @param keep_var_names A list of variable names that should not be frozen,
                          or None to freeze all the variables in the graph.
    @param output_names Names of the relevant graph outputs.
    @param clear_devices Remove the device directives from the graph for better portability.
    @return The frozen graph definition.
    """
    graph = session.graph
    with graph.as_default():
        freeze_var_names = list(set(v.op.name for v in tf.global_variables()).difference(keep_var_names or []))
        output_names = output_names or []
        output_names += [v.op.name for v in tf.global_variables()]
        input_graph_def = graph.as_graph_def()
        if clear_devices:
            for node in input_graph_def.node:
                node.device = ""
        frozen_graph = tf.graph_util.convert_variables_to_constants(
            session, input_graph_def, output_names, freeze_var_names)
        return frozen_graph

这是从 的实现中受到的启发freeze_graph.py。参数也与脚本类似。session是 TensorFlow 会话对象。keep_var_names仅当您想保持某些变量不被冻结时才需要(例如对于有状态模型),所以通常不需要。output_names是一个包含产生所需输出的操作名称的列表。clear_devices只需删除任何设备指令即可使图形更具可移植性。因此,对于具有一个输出的典型 Keras model,您可以执行以下操作:

from keras import backend as K

# Create, compile and train model...

frozen_graph = freeze_session(K.get_session(),
                              output_names=[out.op.name for out in model.outputs])

然后,您可以照常将图表写入文件tf.train.write_graph

tf.train.write_graph(frozen_graph, "some_directory", "my_model.pb", as_text=False)

解决方案 2:

freeze_session 方法工作正常。但与保存到检查点文件相比,使用 TensorFlow 附带的 freeze_graph 工具对我来说似乎更简单,因为它更易于维护。您需要做的只是以下两个步骤:

首先,添加你的 Keras 代码model.fit(...)并训练你的模型:

from keras import backend as K
import tensorflow as tf
print(model.output.op.name)
saver = tf.train.Saver()
saver.save(K.get_session(), '/tmp/keras_model.ckpt')

然后 cd 到你的 TensorFlow 根目录,运行:

python tensorflow/python/tools/freeze_graph.py \n--input_meta_graph=/tmp/keras_model.ckpt.meta \n--input_checkpoint=/tmp/keras_model.ckpt \n--output_graph=/tmp/keras_frozen.pb \n--output_node_names="<output_node_name_printed_in_step_1>" \n--input_binary=true

解决方案 3:

Tensorflow 2 更新

将所有内容保存到 TensorFlow 格式的单个档案中SavedModel(包含saved_model.pb文件):

model = ...  # Get model (Sequential, Functional Model, or Model subclass)
model.save('path/to/location')

或者采用较旧的 KerasH5格式:

model = ...  # Get model (Sequential, Functional Model, or Model subclass)
model.save('model.h5')

建议的格式是SavedModel

重新加载模型:

from tensorflow import keras
model = keras.models.load_model('path/to/location')
model = keras.models.load_model('model.h5')

SavedModel包含完整的 TensorFlow 程序,包括训练参数(即)和计算。它tf.Variables不需要原始模型构建代码即可运行,因此非常适合与TFLiteTensorFlow.jsTensorFlow Serving或共享或部署TensorFlow Hub


Tensorflow 2 示例

以下简单示例(XOR示例)展示了如何导出Keras模型(格式h5pb格式),以及如何在Python和C ++中使用该模型:


训练.py:

import numpy as np
import tensorflow as tf

print(tf.__version__)  # 2.4.1

x_train = np.array([[0, 0], [0, 1], [1, 0], [1, 1]], 'float32')
y_train = np.array([[0], [1], [1], [0]], 'float32')

inputs = tf.keras.Input(shape=(2,), name='input')
x = tf.keras.layers.Dense(64, activation='relu')(inputs)
x = tf.keras.layers.Dense(64, activation='relu')(x)
x = tf.keras.layers.Dense(64, activation='relu')(x)
x = tf.keras.layers.Dense(64, activation="relu")(x)
outputs = tf.keras.layers.Dense(1, activation='sigmoid', name='output')(x)

model = tf.keras.Model(inputs=inputs, outputs=outputs, name='xor')

model.summary()

model.compile(loss='mean_squared_error', optimizer='adam', metrics=['binary_accuracy'])

model.fit(x_train, y_train, epochs=100)

model.save('./xor/')  # SavedModel format

model.save('./xor.h5')  # Keras H5 format

运行上述脚本后:

.
├── train.py
├── xor
│   ├── assets
│   ├── saved_model.pb
│   └── variables
│       ├── variables.data-00000-of-00001
│       └── variables.index
└── xor.h5

预测.py:

import numpy as np
import tensorflow as tf

print(tf.__version__)  # 2.4.1

model = tf.keras.models.load_model('./xor/')  # SavedModel format
# model = tf.keras.models.load_model('./xor.h5')  # Keras H5 format

# 0 xor 0 = [[0.11921611]] ~= 0
print('0 xor 0 = ', model.predict(np.array([[0, 0]])))

# 0 xor 1 = [[0.96736085]] ~= 1
print('0 xor 1 = ', model.predict(np.array([[0, 1]])))

# 1 xor 0 = [[0.97254556]] ~= 1
print('1 xor 0 = ', model.predict(np.array([[1, 0]])))

# 1 xor 1 = [[0.0206149]] ~= 0
print('1 xor 1 = ', model.predict(np.array([[1, 1]])))

将模型转换为 ONNX:

ONNX是交换深度学习模型的新标准。它承诺使深度学习模型可移植,从而避免供应商锁定。

ONNX是一种为表示机器学习模型而构建的开放格式。ONNX定义了一组通用的运算符(机器学习和深度学习模型的构建块)和一种通用的文件格式,使人工智能开发人员能够使用各种框架、工具、运行时和编译器的模型。

$ pip install onnxruntime
$ pip install tf2onnx
$ python -m tf2onnx.convert --saved-model ./xor/ --opset 9 --output xor.onnx

# INFO - Successfully converted TensorFlow model ./xor/ to ONNX
# INFO - Model inputs: ['input:0']
# INFO - Model outputs: ['output']
# INFO - ONNX model is saved at xor.onnx

通过指定,--opset用户可以覆盖默认值以生成具有所需操作集的图形。例如--opset 13,将创建一个仅使用操作集 13 中可用的操作的 onnx 图。由于较旧的操作集在大多数情况下具有较少的操作,因此某些模型可能无法在较旧的操作集上进行转换。


opencv-predict.py:

import numpy as np
import cv2

print(cv2.__version__)  # 4.5.1

model = cv2.dnn.readNetFromONNX('./xor.onnx')

# 0 xor 0 = [[0.11921611]] ~= 0
model.setInput(np.array([[0, 0]]), name='input:0')
print('0 xor 0 = ', model.forward(outputName='output'))

# 0 xor 1 = [[0.96736085]] ~= 1
model.setInput(np.array([[0, 1]]), name='input:0')
print('0 xor 1 = ', model.forward(outputName='output'))

# 1 xor 0 = [[0.97254556]] ~= 1
model.setInput(np.array([[1, 0]]), name='input:0')
print('1 xor 0 = ', model.forward(outputName='output'))

# 1 xor 1 = [[0.02061491]] ~= 0
model.setInput(np.array([[1, 1]]), name='input:0')
print('1 xor 1 = ', model.forward(outputName='output'))

预测.cpp:

#include <cstdlib>
#include <iostream>
#include <opencv2/opencv.hpp>

int main(int argc, char **argv)
{
    std::cout << CV_VERSION << std::endl; // 4.2.0

    cv::dnn::Net net;

    net = cv::dnn::readNetFromONNX("./xor.onnx");

    // 0 xor 0 = [0.11921611] ~= 0
    float x0[] = { 0, 0 };
    net.setInput(cv::Mat(1, 2, CV_32F, x0), "input:0");
    std::cout << "0 xor 0 = " << net.forward("output") << std::endl;

    // 0 xor 1 = [0.96736085] ~= 1
    float x1[] = { 0, 1 };
    net.setInput(cv::Mat(1, 2, CV_32F, x1), "input:0");
    std::cout << "0 xor 1 = " << net.forward("output") << std::endl;

    // 1 xor 0 = [0.97254556] ~= 1
    float x2[] = { 1, 0 };
    net.setInput(cv::Mat(1, 2, CV_32F, x2), "input:0");
    std::cout << "1 xor 0 = " << net.forward("output") << std::endl;

    // 1 xor 1 = [0.020614909] ~= 0
    float x3[] = { 1, 1 };
    net.setInput(cv::Mat(1, 2, CV_32F, x3), "input:0");
    std::cout << "1 xor 1 = " << net.forward("output") << std::endl;

    return EXIT_SUCCESS;
}

编译并运行:

$ sudo apt install build-essential pkg-config libopencv-dev
$ g++ predict.cpp `pkg-config --cflags --libs opencv4` -o predict
$ ./predict

原始答案

以下简单示例(XOR示例)展示了如何导出Keras模型(格式h5pb格式),以及如何在Python和C ++中使用该模型:


训练.py:

import numpy as np
import tensorflow as tf


def freeze_session(session, keep_var_names=None, output_names=None, clear_devices=True):
    """
    Freezes the state of a session into a pruned computation graph.

    Creates a new computation graph where variable nodes are replaced by
    constants taking their current value in the session. The new graph will be
    pruned so subgraphs that are not necessary to compute the requested
    outputs are removed.
    @param session The TensorFlow session to be frozen.
    @param keep_var_names A list of variable names that should not be frozen,
                          or None to freeze all the variables in the graph.
    @param output_names Names of the relevant graph outputs.
    @param clear_devices Remove the device directives from the graph for better portability.
    @return The frozen graph definition.
    """
    graph = session.graph
    with graph.as_default():
        freeze_var_names = list(set(v.op.name for v in tf.global_variables()).difference(keep_var_names or []))
        output_names = output_names or []
        output_names += [v.op.name for v in tf.global_variables()]
        input_graph_def = graph.as_graph_def()
        if clear_devices:
            for node in input_graph_def.node:
                node.device = ''
        frozen_graph = tf.graph_util.convert_variables_to_constants(
            session, input_graph_def, output_names, freeze_var_names)
        return frozen_graph


X = np.array([[0,0], [0,1], [1,0], [1,1]], 'float32')
Y = np.array([[0], [1], [1], [0]], 'float32')

model = tf.keras.models.Sequential()
model.add(tf.keras.layers.Dense(64, input_dim=2, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))

model.compile(loss='mean_squared_error', optimizer='adam', metrics=['binary_accuracy'])

model.fit(X, Y, batch_size=1, nb_epoch=100, verbose=0)

# inputs:  ['dense_input']
print('inputs: ', [input.op.name for input in model.inputs])

# outputs:  ['dense_4/Sigmoid']
print('outputs: ', [output.op.name for output in model.outputs])

model.save('./xor.h5')

frozen_graph = freeze_session(tf.keras.backend.get_session(), output_names=[out.op.name for out in model.outputs])
tf.train.write_graph(frozen_graph, './', 'xor.pbtxt', as_text=True)
tf.train.write_graph(frozen_graph, './', 'xor.pb', as_text=False)

预测.py:

import numpy as np
import tensorflow as tf

model = tf.keras.models.load_model('./xor.h5')

# 0 ^ 0 =  [[0.01974997]]
print('0 ^ 0 = ', model.predict(np.array([[0, 0]])))

# 0 ^ 1 =  [[0.99141496]]
print('0 ^ 1 = ', model.predict(np.array([[0, 1]])))

# 1 ^ 0 =  [[0.9897714]]
print('1 ^ 0 = ', model.predict(np.array([[1, 0]])))

# 1 ^ 1 =  [[0.00406971]]
print('1 ^ 1 = ', model.predict(np.array([[1, 1]])))

opencv-predict.py:

import numpy as np
import cv2 as cv


model = cv.dnn.readNetFromTensorflow('./xor.pb')

# 0 ^ 0 =  [[0.01974997]]
model.setInput(np.array([[0, 0]]), name='dense_input')
print('0 ^ 0 = ', model.forward(outputName='dense_4/Sigmoid'))

# 0 ^ 1 =  [[0.99141496]]
model.setInput(np.array([[0, 1]]), name='dense_input')
print('0 ^ 1 = ', model.forward(outputName='dense_4/Sigmoid'))

# 1 ^ 0 =  [[0.9897714]]
model.setInput(np.array([[1, 0]]), name='dense_input')
print('1 ^ 0 = ', model.forward(outputName='dense_4/Sigmoid'))

# 1 ^ 1 =  [[0.00406971]]
model.setInput(np.array([[1, 1]]), name='dense_input')
print('1 ^ 1 = ', model.forward(outputName='dense_4/Sigmoid'))

预测.cpp:

#include <cstdlib>
#include <iostream>
#include <opencv2/opencv.hpp>

int main(int argc, char **argv)
{
    cv::dnn::Net net;

    net = cv::dnn::readNetFromTensorflow("./xor.pb");

    // 0 ^ 0 = [0.018541215]
    float x0[] = { 0, 0 };
    net.setInput(cv::Mat(1, 2, CV_32F, x0), "dense_input");
    std::cout << "0 ^ 0 = " << net.forward("dense_4/Sigmoid") << std::endl;

    // 0 ^ 1 = [0.98295897]
    float x1[] = { 0, 1 };
    net.setInput(cv::Mat(1, 2, CV_32F, x1), "dense_input");
    std::cout << "0 ^ 1 = " << net.forward("dense_4/Sigmoid") << std::endl;

    // 1 ^ 0 = [0.98810625]
    float x2[] = { 1, 0 };
    net.setInput(cv::Mat(1, 2, CV_32F, x2), "dense_input");
    std::cout << "1 ^ 0 = " << net.forward("dense_4/Sigmoid") << std::endl;

    // 1 ^ 1 = [0.010002014]
    float x3[] = { 1, 1 };
    net.setInput(cv::Mat(1, 2, CV_32F, x3), "dense_input");
    std::cout << "1 ^ 1 = " << net.forward("dense_4/Sigmoid") << std::endl;

    return EXIT_SUCCESS;
}

解决方案 4:

目前,以上所有旧答案都已过时。截至 Tensorflow 2.1

from tensorflow.keras.models import Model, load_model
model = load_model(MODEL_FULLPATH)
model.save(MODEL_FULLPATH_MINUS_EXTENSION)

将创建一个包含“saved_model.pb”的文件夹

解决方案 5:

当你想转换成 tensorflow 时,有一个非常重要的点。如果你使用 dropout、batch normalization 或任何其他类似的层(它们没有可训练但有计算值),你应该更改 keras 后端的学习阶段。这里有一个关于它的讨论。

import keras.backend as K
k.set_learning_phase(0) # 0 testing, 1 training mode

解决方案 6:

这个解决方案对我有用。感谢https://medium.com/tensorflow/training-and-serving-ml-models-with-tf-keras-fd975cc0fa27

import tensorflow as tf

# The export path contains the name and the version of the model
tf.keras.backend.set_learning_phase(0) # Ignore dropout at inference
model = tf.keras.models.load_model('./model.h5')
export_path = './PlanetModel/1'

# Fetch the Keras session and save the model
# The signature definition is defined by the input and output tensors
# And stored with the default serving key
with tf.keras.backend.get_session() as sess:
    tf.saved_model.simple_save(
        sess,
        export_path,
        inputs={'input_image': model.input},
        outputs={t.name:t for t in model.outputs})

解决方案 7:

请使用tf.saved_model.simple_save,一些示例代码:

with tf.keras.backend.get_session() as sess:
    tf.saved_model.simple_save(
        sess,
        export_path,
        inputs={'input': keras_model.input},
        outputs={'output': keras_model.output})

===更新====

您可以使用as_a_saved_model,示例代码:

saved_model_path = tf.contrib.saved_model.save_keras_model(model, "./saved_models")

解决方案 8:

如果你只想使用模型进行推理,那么你应该先冻结图形,然后将其写入.pb文件。代码片段如下所示(代码借自此处):

import tensorflow as tf
from tensorflow.python.framework import graph_util
from tensorflow.python.framework import graph_io
import keras
from keras import backend as K

sess = K.get_session()

constant_graph = graph_util.convert_variables_to_constants(
        sess,
        sess.graph.as_graph_def(),
        ["name_of_the_output_graph_node"])

graph_io.write_graph(constant_graph, "path/to/output/folder", 
                     "output_model_name", as_text=False)

您可以使用keras_to_tensorflow工具完成上述操作:https://github.com/amir-abdi/keras_to_tensorflow

keras_to_tensorflow工具负责上述操作,并提供一些额外功能以实现更多样化的解决方案。只需使用正确的输入参数(例如input_modeloutput_model标志)调用它即可。

如果您想在 TensorFlow 中重新训练模型,请使用上述工具和output_meta_ckpt标志导出检查点和元图。

解决方案 9:

使用 estimator.export_savedmodel 我们可以轻松地将 h5 模型转换为已保存的模型。在此处查看文档https://www.tensorflow.org/api_docs/python/tf/estimator/Estimator

def prepare_image(image_str_tensor):
    image_contents = tf.read_file(image_str_tensor)
    image = tf.image.decode_jpeg(image_contents, channels=3)
    image = tf.image.resize_images(image, [224, 224])
    image = tf.cast(image, tf.float32)
    return preprocess_input(image)

def serving_input_receiver_fn():
    input_ph = tf.placeholder(tf.string, shape=[None])
    images_tensor = tf.map_fn(
          prepare_image, input_ph, back_prop=False, dtype=tf.float32)
    images_tensor = tf.image.convert_image_dtype(images_tensor, 
                      dtype=tf.float32)

    return tf.estimator.export.ServingInputReceiver({"input": images_tensor}, 
             {'image_url': input_ph})

estimator = tf.keras.estimator.model_to_estimator(
    keras_model_path=h5_model_path
)

estimator.export_savedmodel(saved_model_path, serving_input_receiver_fn=serving_input_receiver_fn)

解决方案 10:

Tensorflow tf.saved_model api 最适合生成 pb 模型

如果你有 h5 模型,则通过 keras load_model 加载它

from tensorflow import keras
model = keras.models.load_model("model.h5")

通过 saved_model api 保存 tensorflow 模型,它将以 pb 格式保存模型。此模型将具有通过 Google Ai Platform 提供服务所需的元数据。因此,您可以将目录上传到 Ai Platform 以提供您的模型。

import tensorflow as tf
tf.saved_model.save(model, './directory-to-save-file/')

解决方案 11:

tf 2.2.0

导入 tensorflow.keras 而不是仅仅 keras,因为它会将您的模型加载为 keras.engine.sequential.Sequential 对象,而该对象不能直接转换为 tensorflow .pb 格式

#import keras
import tensorflow.keras as keras
model = keras.models.load_model(load_path)
model.save(save_path)

解决方案 12:

使用tensorflow 2.x:如果您只想保存图形定义,pbtxt请使用以下代码。

import tensorflow as tf
keras_model = ...
tf.io.write_graph(
  keras_model.output.graph,
  'model_dir',
  'model.pbtxt',
  as_text=True,
)

解决方案 13:

如果用户试图将 Mask-RCNN 模型/权重转换为冻结图,这里的大多数答案都不够用。

这可以在文件中保存模型 ( .h5) 权重时完成mrcnn/model.py。只需进行以下更改 ( git diff)

+    def freeze_session(self, session, keep_var_names=None, output_names=None, clear_devices=True):
+        """
+        Freezes the state of a session into a pruned computation graph.
+
+        Creates a new computation graph where variable nodes are replaced by
+        constants taking their current value in the session. The new graph will be
+        pruned so subgraphs that are not necessary to compute the requested
+        outputs are removed.
+        @param session The TensorFlow session to be frozen.
+        @param keep_var_names A list of variable names that should not be frozen,
+                              or None to freeze all the variables in the graph.
+        @param output_names Names of the relevant graph outputs.
+        @param clear_devices Remove the device directives from the graph for better portability.
+        @return The frozen graph definition.
+        """
+        graph = session.graph
+        with graph.as_default():
+            freeze_var_names = list(set(v.op.name for v in tf.global_variables()).difference(keep_var_names or []))
+            output_names = output_names or []
+            output_names += [v.op.name for v in tf.global_variables()]
+            input_graph_def = graph.as_graph_def()
+            if clear_devices:
+                for node in input_graph_def.node:
+                    node.device = ""
+            frozen_graph = tf.graph_util.convert_variables_to_constants(
+                session, input_graph_def, output_names, freeze_var_names)
+            return frozen_graph
+
     def train(self, train_dataset, val_dataset, learning_rate, epochs, layers,
               augmentation=None, custom_callbacks=None, no_augmentation_sources=None):
         """Train the model.
@@ -2373,6 +2401,12 @@ class MaskRCNN():
             workers=workers,
             use_multiprocessing=True,
         )
+        #######using session and saving .pb file##
+        frozen_graph = self.freeze_session(K.get_session(),
+                              output_names=[out.op.name for out in self.keras_model.outputs])
+        print('

        ******* Writing Frozen Graph in logs directory *******

')
+        tf.train.write_graph(frozen_graph, self.log_dir, "my_model.pb", as_text=False)
+
         self.epoch = max(self.epoch, epochs)

完整文件可在此处找到。有了它,我能够将 ResNet50 和 ResNet101 主干转换为 coco 和 imagenet 权重。

解决方案 14:

就我而言,我尝试将暗网权重转换为 TensorFlow 模型,我需要 .pb 格式的模型。我尝试了这里以及其他论坛上给出的许多解决方案,但最终我通过将 Tensorflow v2.2 升级到 Tensorflow v2.3 解决了这个问题,并且我可以成功将模型保存为 .pb 格式。

以下是可供参考的文档:

我的进口商品:

import tensorflow as tf
import tensorflow.keras as keras

以.pb 格式保存模型的代码:

model.save("/path to directory/")

以.h5格式保存模型的代码:

tf.keras.models.save_model(model = model, filepath, modelname.h5')

注意:只有将 Tensorflow 从 2.2 版升级到 2.3 版后才能实现此功能

相关推荐
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1325  
  IPD(Integrated Product Development)流程作为一种先进的产品开发管理模式,在众多企业中得到了广泛应用。它涵盖了从产品概念产生到产品退市的整个生命周期,通过整合跨部门团队、优化流程等方式,显著提升产品开发的效率和质量,进而为项目的成功奠定坚实基础。深入探究IPD流程的五个阶段与项目成功之间...
IPD流程分为几个阶段   4  
  华为作为全球知名的科技企业,其成功背后的管理体系备受关注。IPD(集成产品开发)流程作为华为核心的产品开发管理模式,其中的创新管理与实践更是蕴含着丰富的经验和深刻的智慧,对众多企业具有重要的借鉴意义。IPD流程的核心架构IPD流程旨在打破部门墙,实现跨部门的高效协作,将产品开发视为一个整体的流程。它涵盖了从市场需求分析...
华为IPD是什么   3  
  IPD(Integrated Product Development)研发管理体系作为一种先进的产品开发模式,在众多企业的发展历程中发挥了至关重要的作用。它不仅仅是一套流程,更是一种理念,一种能够全方位提升企业竞争力,推动企业持续发展的有效工具。深入探究IPD研发管理体系如何助力企业持续发展,对于众多渴望在市场中立足并...
IPD管理流程   3  
  IPD(Integrated Product Development)流程管理旨在通过整合产品开发流程、团队和资源,实现产品的快速、高质量交付。在这一过程中,有效降低成本是企业提升竞争力的关键。通过优化IPD流程管理中的各个环节,可以在不牺牲产品质量和性能的前提下,实现成本的显著降低,为企业创造更大的价值。优化产品规划...
IPD流程分为几个阶段   4  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用