Skip to content

Conversation

@avolkov-intel
Copy link

Changes

Added implementation of profiler to collect and compare activations value of openVino model to investigate cause of accuracy degradation.

Reason for changes

Related tickets

162317

Tests

Copy link
Contributor

@ljaljushkin ljaljushkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the contribution, Anatoly!
Please consider adding visualization functionality and enhancing the scalability

@github-actions github-actions bot added the documentation Improvements or additions to documentation label Dec 3, 2025
@SearchSavior
Copy link

Wonderful addition!!!!

@avolkov-intel once merged I will test on

Hermes-14B
Wayfarer-2-12B

Thanks you for your work.

Comment on lines +302 to +317
# Extract and convert collected statistics to numpy arrays
result: ActivationData = {}
for layer_name, statistic_points_list in statistics_aggregator.statistic_points.items():
# Extract input activations (index 1 in statistic_points_list)
in_container = list(
statistic_points_list[1].algorithm_to_tensor_collectors["collect"][0].aggregators.values()
)[0]._container
in_vals = [np.array(elem.data) for elem in in_container]

# Extract output activations (index 0 in statistic_points_list)
out_container = list(
statistic_points_list[0].algorithm_to_tensor_collectors["collect"][0].aggregators.values()
)[0]._container
out_vals = [np.array(elem.data) for elem in out_container]

result[layer_name] = {"in": in_vals, "out": out_vals}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Statistic collection API

Suggested change
# Extract and convert collected statistics to numpy arrays
result: ActivationData = {}
for layer_name, statistic_points_list in statistics_aggregator.statistic_points.items():
# Extract input activations (index 1 in statistic_points_list)
in_container = list(
statistic_points_list[1].algorithm_to_tensor_collectors["collect"][0].aggregators.values()
)[0]._container
in_vals = [np.array(elem.data) for elem in in_container]
# Extract output activations (index 0 in statistic_points_list)
out_container = list(
statistic_points_list[0].algorithm_to_tensor_collectors["collect"][0].aggregators.values()
)[0]._container
out_vals = [np.array(elem.data) for elem in out_container]
result[layer_name] = {"in": in_vals, "out": out_vals}
# Extract and convert collected statistics to numpy arrays
result: ActivationData = defaultdict(dict)
target_type_to_str = {
TargetType.PRE_LAYER_OPERATION: "in",
TargetType.POST_LAYER_OPERATION: "out",
}
for _, statistic_point, tensor_collector in statistic_points.get_tensor_collectors():
if statistic_point.target_point.type not in target_type_to_str:
msg = f"Unsupported target type: {statistic_point.target_point.type}"
raise RuntimeError(msg)
insert_type = target_type_to_str[statistic_point.target_point.type]
layer_name = statistic_point.target_point.target_node_name
stats = tensor_collector.get_statistics().values
result[layer_name][insert_type] = [np.array(elem.data) for elem in stats]

msg = f"No layers found matching pattern: {pattern}"
raise ValueError(msg)

target_ops = [graph.get_node_by_key(name) for name in target_names]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sort nodes in topographical order. Currently nodes are sorted by lexicographical order

Suggested change
target_ops = [graph.get_node_by_key(name) for name in target_names]
target_ops = []
for node in graph.topological_sort():
if len(target_ops) == len(target_names):
break
if node.node_key in target_names:
target_ops.append(node)

Comment on lines +71 to +89
"def transform_fn(data, tokenizer):\n",
" tokenized_text = tokenizer(data[\"text\"], return_tensors=\"np\")\n",
" input_ids = tokenized_text[\"input_ids\"]\n",
" attention_mask = tokenized_text[\"attention_mask\"]\n",
"\n",
" inputs = {}\n",
" inputs[\"input_ids\"] = input_ids\n",
" inputs[\"attention_mask\"] = tokenized_text[\"attention_mask\"]\n",
" position_ids = np.cumsum(attention_mask, axis=1) - 1\n",
" position_ids[attention_mask == 0] = 1\n",
" inputs[\"position_ids\"] = position_ids\n",
"\n",
" batch_size = input_ids.shape[0]\n",
" inputs[\"beam_idx\"] = np.arange(batch_size, dtype=int)\n",
"\n",
" return inputs\n",
"\n",
"\n",
"quantization_dataset = nncf.Dataset(dataset, partial(transform_fn, tokenizer=tokenizer))"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm suggesting to use following model-agnostic sniped there

from optimum.gptq.data import get_dataset
from optimum.gptq.data import prepare_dataset

dataset = "wikitext2"
seqlen = 50
nsamples = 2
calibration_dataset = get_dataset(dataset, tokenizer, seqlen=seqlen, nsamples=nsamples)
calibration_dataset = prepare_dataset(calibration_dataset)
quantization_dataset = nncf.Dataset(calibration_dataset, lambda x: model.prepare_inputs(**x))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants