Сортировка карты из более чем 50 тысяч записей занимает слишком много времени. Есть ли более быстрый способ отсортировать карту в dart?

#sorting #dart

#сортировка #dart

Вопрос:

У меня есть значения вероятности, возвращаемые из нейронной сети. Размер возвращаемого списка равен 50 257, поэтому значений много. Список выглядит следующим образом [-126.32508850097656, -126.77257537841797, -127.69950866699219, -129.98387145996094, ......]

Мне нужны верхние K значений и их индексы. Итак, я преобразовал список в карту:

final temp = outputLogits.asMap();

а затем отсортировали их с помощью:

 var sortedKeys = temp.keys.toList(growable: false)
      ..sort((k1, k2) => temp[k2].compareTo(temp[k1]));
 

Это дает желаемый результат, но проблема в том, что это занимает слишком много времени.

Я делаю это неправильно? есть ли более эффективный способ получить тот же результат?

дополнительная информация:

Несортированный список выглядит следующим образом:

 [-126.32508850097656, -126.77257537841797, -127.69950866699219, -129.98387145996094, -128.03782653808594, -128.08395385742188, -126.33218383789062, -126.6927261352539, -127.6688232421875, -126.58303833007812, -127.32843017578125, -126.1390380859375, -126.54962158203125, -126.38087463378906, -127.82595825195312, -126.3281021118164, -125.81211853027344, -126.20887756347656, -125.95697784423828, -126.07755279541016, -126.35894012451172, -126.70021057128906, -127.03215026855469, -126.67304992675781, -126.92938995361328, -126.64434814453125, -128.20814514160156, -127.24195861816406, -128.25816345214844, -126.73397827148438, -127.62574768066406, -128.8334197998047, -124.46258544921875, -126.03125762939453, -126.18477630615234, -125.85749053955078, -126.11980438232422, -125.64325714111328, -126.06704711914062, -126.35154724121094, -124.83910369873047, -126.90412902832031, -126.02999877929688, -126.60641479492188, -125.97348022460938, -126.56074523925781, -126.58230590820312, -126.49268341064453, -128.5759735107422,
 

Мне нужно найти 40 лучших вероятностей и их индекс, и я достигаю этого с помощью:

 final temp = outputLogits.asMap();                            // converts the above list to a Map<int, double>
    // sort the map values descending
    // then take the largest 40 values
    var sortedKeys = temp.keys.toList(growable: false)
      ..sort((k1, k2) => temp[k2].compareTo(temp[k1]));           
    final Map<int, double> sortedMap = {};

    for (final key in sortedKeys.take(40)) {                    
      sortedMap[key] = temp[key];
    }
 

после сортировки это sortedMap выглядит так:

 {198: -117.52079772949219, 383: -118.29053497314453, 887: -119.25838470458984, 1119: -119.66973876953125, 632: -119.74752807617188, 628: -119.87970733642578, 554: -119.88958740234375, 1081: -119.9058837890625, 843: -120.10496520996094, 317: -120.21776580810547, 2102: -120.23406982421875, 770: -120.31946563720703, 2293: -120.40717315673828, 1649: -120.44376373291016, 366: -120.47624969482422, 2080: -120.4794921875, 2735: -120.74302673339844, 3244: -120.89102935791016, 2893: -120.97686004638672, 314: -120.98660278320312, 5334: -121.00469970703125, 1318: -121.03706359863281, 679: -121.12769317626953, 1881: -121.14120483398438, 1629: -121.18737030029297, 50256: -121.19244384765625, 357: -121.22344207763672, 1550: -121.27531433105469, 775: -121.31112670898438, 7486: -121.3316421508789, 921: -121.37474060058594, 1114: -121.43411254882812, 2312: -121.43602752685547, 1675: -121.51364135742188, 4874: -121.5697021484375, 1867: -121.57322692871094, 1439: -121.60330963134766, 8989: -121.60348510742188, 1320: -121.604621
 

Мне нужно верхнее значение и их соответствующий индекс, поэтому они преобразуются в Map

Комментарии:

1. Можете ли вы привести небольшой пример с некоторыми данными и ожидаемым результатом? Причина в том, что мне нужно попытаться понять необходимость использования a Map . Кроме того, вы могли бы правильно пропустить множество поисковых запросов на карте, используя entries вместо keys но опять же, я хотел бы немного лучше понять проблему, прежде чем рекомендовать что-то конкретное.

2. @julemand101, я добавил код, который пытаюсь воспроизвести. По сути, модель возвращает логиты для каждого словаря [в данном случае 5027], а для генерации текста и выбора «следующего» слова необходимы 40 лучших слов с наибольшей вероятностью, из которых выбирается следующее слово для продолжения генерации текста

3. Пожалуйста, предоставьте минимальный пример, показывающий, что у вас есть в качестве входных данных перед сортировкой и что вы хотите получить в результате сортировки. Я не собираюсь полагаться на Kotlin и читать несколько страниц статьи по теме, которая меня не интересует, просто чтобы предоставить вам наилучший способ сортировки списка…

4. @julemand101, ааа, понял. Извините, просто хотел дать полный контекст того, чего я пытаюсь достичь, поскольку вы спросили, почему я перешел на Map, не пытался быть ленивым :). Я добавил больше деталей к своему вопросу. Это нормально?

5. Да, это выглядит нормально. Я дам ответ, как только у меня будет рабочий пример для вас. 🙂

Ответ №1:

Попробуйте следующее:

 void main() {
  final temp = [
    -126.32508850097656,
    -126.77257537841797,
    -127.69950866699219,
    -129.98387145996094,
    -128.03782653808594,
    -128.08395385742188,
    -126.33218383789062,
    -126.6927261352539,
    -127.6688232421875,
    -126.58303833007812,
    -127.32843017578125,
  ];

  final filteredLogitsWithIndexes = Map.fromEntries(
      (temp.asMap().entries.toList(growable: false)
            ..sort((e1, e2) => e2.value.compareTo(e1.value)))
          .take(5));

  print(filteredLogitsWithIndexes);
  // {0: -126.32508850097656, 6: -126.33218383789062, 9: -126.58303833007812,
  // 7: -126.6927261352539, 1: -126.77257537841797}
}
 

Это должно сэкономить вам много времени, поскольку нам не нужно выполнять поиск на карте для каждого сравнения (поскольку a MapEntry содержит оба key и value ).

Комментарии:

1. Большое вам спасибо, это действительно значительно быстрее <3

2. извините, что спрашиваю еще раз, но возможно ли дополнительно оптимизировать эту задачу? Я пишу приложение NLP, которое генерирует текст, и сейчас на написание слова уходит около 5 секунд. Итак, просто спрашиваю, можно ли еще больше увеличить скорость сортировки, хотя бы немного, что сократило бы секунду? Спасибо

3. @StuckInPhDNoMore Можете ли вы сослаться на какой-нибудь пример проекта с включенными тестовыми данными, которые показывают текущую производительность? Возможно, мне будет проще проанализировать, где проблемы с производительностью, и попытаться выполнить оптимизацию. Вы также можете связаться со мной напрямую, используя почту в моем профиле на github (для ее просмотра вам необходимо войти в систему): github.com/julemand101

4. итак, я провел некоторую отладку, и, похоже, большую часть времени занимал вывод модели тензорного потока. Большое спасибо за вашу помощь. 🙂