Yardım Kaggle üzerinde TensorFlow ile Büyük Bariyer Resifi korumak Meydan Üyelik

TF 1.x ve compat.v1 API sembollerini otomatik olarak yeniden yazın

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Not defterini indir

TensorFlow 2.x birçok TF 1.x API değişikliklerini ve kapsamaktadır tf.compat.v1 böyle, argümanları yeniden sıralama sembolleri yeniden adlandırma ve parametreler için varsayılan değerleri değiştirmek gibi API'ler. Tüm bu değişiklikleri manuel olarak gerçekleştirmek sıkıcı ve hataya açık olacaktır. Değişiklikleri düzene için, ve mümkün olduğunca kesintisiz olarak TF 2.x için geçiş yapmaya, TensorFlow ekibi yarattı tf_upgrade_v2 yeni API yardım geçiş eski koduna yarar.

Tipik kullanım şu şekildedir:

tf_upgrade_v2 \
  --intree my_project/ \
  --outtree my_project_v2/ \
  --reportfile report.txt

Mevcut TensorFlow 1.x Python komut dosyalarını TensorFlow 2.x'e dönüştürerek yükseltme sürecinizi hızlandıracaktır.

Çoğu API otomatik olarak taşınamasa da, dönüştürme komut dosyası birçok mekanik API dönüşümünü otomatikleştirir. Ayrıca kodunuzu TF2 davranışları ve API'leri ile tam olarak uyumlu hale getiremez. Yani, göç yolculuğunuzun sadece bir parçası.

Uyumluluk modülleri

Belirli API sembolleri, yalnızca bir dize değişimi kullanılarak yükseltilemez. Otomatik olarak yeni sürüme edilemez olanlar, bulundukları konumda eşlenir compat.v1 modülü. Bu modül gibi TF 1.x sembolleri değiştirir tf.foo eşdeğeri ile tf.compat.v1.foo referans. Zaten kullanıyorsanız compat.v1 aracılığıyla TF ithal ederek API'leri import tensorflow.compat.v1 as tf , tf_upgrade_v2 komut mümkünse olmayan compat API'ler bu kullanımlarını dönüştürmek için çalışacaktır. Bazı ederken Not olduğunu compat.v1 API'ler TF2.x davranışları ile uyumludur, birçok değildir. Yani, biz el tashih değiştirmeler ve yeni API'ler onları taşımanızı öneriyoruz tf.* Ad yerine tf.compat.v1 çabuk mümkün olduğunca ad.

Çünkü TensorFlow 2.x modülü deprecations (örnek için tf.flags ve tf.contrib ) bazı değişiklikler geçerek etrafında çalışmış edilemez compat.v1 . Bu kod yükseltme ek kütüphane (örneğin, kullanılarak gerektirebilir absl.flags bir pakete) ya da anahtarlama tensorflow / eklentileri .

Bu kılavuzun geri kalanı, sembol yeniden yazma komut dosyasının nasıl kullanılacağını gösterir. Komut dosyasının kullanımı kolay olsa da, komut dosyasını aşağıdaki işlemin bir parçası olarak kullanmanız şiddetle önerilir:

  1. Birim Test: Kod Sen yükseltme makul kapsama sahip bir birim test paketi sahip olduğundan emin olun. Bu Python kodudur, dolayısıyla dil sizi birçok hata sınıfından korumayacaktır. Ayrıca, sahip olduğunuz tüm bağımlılıkların TensorFlow 2.x ile uyumlu olacak şekilde yükseltildiğinden emin olun.

  2. TensorFlow 1.15 yükleyin: son TensorFlow 1.x sürüme TensorFlow yükseltin, en azından 1.15. Bu son TensorFlow 2.0 API içerir tf.compat.v2 .

  3. Testi ile 1.15: En birim testleri bu noktada geçmesi sağlayın. Yükseltme yaparken bunları tekrar tekrar çalıştıracaksınız, bu nedenle yeşilden başlamak önemlidir.

  4. Yükseltme komut dosyasını çalıştırın: Run tf_upgrade_v2 tüm kaynak ağacındaki, testler dahil. Bu, kodunuzu yalnızca TensorFlow 2.0'da bulunan sembollerin kullanıldığı bir biçime yükseltir. Kaldırıldı, semboller ile erişilen tf.compat.v1 . Bunlar nihayetinde manuel müdahale gerektirecektir, ancak hemen değil.

  5. TensorFlow 1.15 ile dönüştürülen testleri çalıştırın: Kodunuz hala TensorFlow 1.15 yılında cezası çalışmalıdır. Birim testlerinizi tekrar çalıştırın. Buradaki testlerinizde herhangi bir hata olması, yükseltme komut dosyasında bir hata olduğu anlamına gelir. Bize bildirin .

  6. Uyarı ve hataları yükseltme raporunu kontrol: komut herhangi Eğer çift-çek gereken dönüşümleri veya atmanız gereken manuel bir işlem açıklayan bir rapor dosyası yazar. Örneğin: Kalan tüm katkı örneklerinin kaldırılması için manuel işlem yapılması gerekir. Danışın fazla talimat için RFC .

  7. TensorFlow 2.x yükleyin: Bu noktada TensorFlow için 2.x ikilileri geçmek için güvenli olmalı, eski davranışları ile çalışan bile

  8. İle test v1.disable_v2_behavior : Bir ile testlerle yeniden çalıştıran v1.disable_v2_behavior() 1.15 altında çalışan aynı sonuçları vermelidir testler yapılarak analiz ana işlevi.

  9. V2 Davranışı etkinleştirme: Şimdi testler TF2 ikilileri kullanarak çalıştığını, şimdi kaçınarak kodunuzu göç başlayabilir tf.estimator ler ve sadece (devre dışı bırakma hiçbir TF2 davranışıyla) desteklenen TF2 davranışları kullanarak. Bkz Göç kılavuzları Ayrıntılar için.

Sembol-yeniden yazma kullanarak tf_upgrade_v2 komut

Kurmak

Başlamadan önce TensorFlow 2.x'in kurulu olduğundan emin olun.

import tensorflow as tf

print(tf.__version__)
2.6.0

Klon tensorflow / modeller üzerinde test etmek için bazı kod var bu yüzden git depo:

git clone --branch r1.13.0 --depth 1 https://github.com/tensorflow/models
Cloning into 'models'...
remote: Enumerating objects: 2927, done.[K
remote: Counting objects: 100% (2927/2927), done.[K
remote: Compressing objects: 100% (2428/2428), done.[K
remote: Total 2927 (delta 504), reused 2113 (delta 424), pack-reused 0[K
Receiving objects: 100% (2927/2927), 369.04 MiB | 27.58 MiB/s, done.
Resolving deltas: 100% (504/504), done.
Checking out files: 100% (2768/2768), done.

Yardımı okuyun

Komut dosyası TensorFlow ile kurulmalıdır. İşte yerleşik yardım:

tf_upgrade_v2 -h
usage: tf_upgrade_v2 [-h] [--infile INPUT_FILE] [--outfile OUTPUT_FILE]
                     [--intree INPUT_TREE] [--outtree OUTPUT_TREE]
                     [--copyotherfiles COPY_OTHER_FILES] [--inplace]
                     [--no_import_rename] [--no_upgrade_compat_v1_import]
                     [--reportfile REPORT_FILENAME] [--mode {DEFAULT,SAFETY}]
                     [--print_all]

Convert a TensorFlow Python file from 1.x to 2.0

Simple usage:
  tf_upgrade_v2.py --infile foo.py --outfile bar.py
  tf_upgrade_v2.py --infile foo.ipynb --outfile bar.ipynb
  tf_upgrade_v2.py --intree ~/code/old --outtree ~/code/new

optional arguments:
  -h, --help            show this help message and exit
  --infile INPUT_FILE   If converting a single file, the name of the file to
                        convert
  --outfile OUTPUT_FILE
                        If converting a single file, the output filename.
  --intree INPUT_TREE   If converting a whole tree of files, the directory to
                        read from (relative or absolute).
  --outtree OUTPUT_TREE
                        If converting a whole tree of files, the output
                        directory (relative or absolute).
  --copyotherfiles COPY_OTHER_FILES
                        If converting a whole tree of files, whether to copy
                        the other files.
  --inplace             If converting a set of files, whether to allow the
                        conversion to be performed on the input files.
  --no_import_rename    Not to rename import to compat.v2 explicitly.
  --no_upgrade_compat_v1_import
                        If specified, don't upgrade explicit imports of
                        `tensorflow.compat.v1 as tf` to the v2 APIs.
                        Otherwise, explicit imports of the form
                        `tensorflow.compat.v1 as tf` will be upgraded.
  --reportfile REPORT_FILENAME
                        The name of the file where the report log is
                        stored.(default: report.txt)
  --mode {DEFAULT,SAFETY}
                        Upgrade script mode. Supported modes: DEFAULT: Perform
                        only straightforward conversions to upgrade to 2.0. In
                        more difficult cases, switch to use compat.v1. SAFETY:
                        Keep 1.* code intact and import compat.v1 module.
  --print_all           Print full log to stdout instead of just printing
                        errors

Örnek TF1 kodu

İşte basit bir TensorFlow 1.0 betiği:

head -n 65 models/samples/cookbook/regression/custom_regression.py | tail -n 10
# Calculate loss using mean squared error
  average_loss = tf.losses.mean_squared_error(labels, predictions)

  # Pre-made estimators use the total_loss instead of the average,
  # so report total_loss for compatibility.
  batch_size = tf.shape(labels)[0]
  total_loss = tf.to_float(batch_size) * average_loss

  if mode == tf.estimator.ModeKeys.TRAIN:
    optimizer = params.get("optimizer", tf.train.AdamOptimizer)

TensorFlow 2.x kuruluyken çalışmaz:

(cd models/samples/cookbook/regression && python custom_regression.py)
Traceback (most recent call last):
  File "custom_regression.py", line 162, in <module>
    tf.logging.set_verbosity(tf.logging.INFO)
AttributeError: module 'tensorflow' has no attribute 'logging'

Tek dosya

Komut dosyası tek bir Python dosyasında çalıştırılabilir:

!tf_upgrade_v2 \
  --infile models/samples/cookbook/regression/custom_regression.py \
  --outfile /tmp/custom_regression_v2.py
INFO line 38:8: Renamed 'tf.feature_column.input_layer' to 'tf.compat.v1.feature_column.input_layer'
INFO line 43:10: Renamed 'tf.layers.dense' to 'tf.compat.v1.layers.dense'
INFO line 46:17: Renamed 'tf.layers.dense' to 'tf.compat.v1.layers.dense'
INFO line 57:17: tf.losses.mean_squared_error requires manual check. tf.losses have been replaced with object oriented versions in TF 2.0 and after. The loss function calls have been converted to compat.v1 for backward compatibility. Please update these calls to the TF 2.0 versions.
INFO line 57:17: Renamed 'tf.losses.mean_squared_error' to 'tf.compat.v1.losses.mean_squared_error'
INFO line 61:15: Added keywords to args of function 'tf.shape'
INFO line 62:15: Changed tf.to_float call to tf.cast(..., dtype=tf.float32).
INFO line 65:40: Renamed 'tf.train.AdamOptimizer' to 'tf.compat.v1.train.AdamOptimizer'
INFO line 68:39: Renamed 'tf.train.get_global_step' to 'tf.compat.v1.train.get_global_step'
INFO line 83:9: tf.metrics.root_mean_squared_error requires manual check. tf.metrics have been replaced with object oriented versions in TF 2.0 and after. The metric function calls have been converted to compat.v1 for backward compatibility. Please update these calls to the TF 2.0 versions.
INFO line 83:9: Renamed 'tf.metrics.root_mean_squared_error' to 'tf.compat.v1.metrics.root_mean_squared_error'
INFO line 142:23: Renamed 'tf.train.AdamOptimizer' to 'tf.compat.v1.train.AdamOptimizer'
INFO line 162:2: Renamed 'tf.logging.set_verbosity' to 'tf.compat.v1.logging.set_verbosity'
INFO line 162:27: Renamed 'tf.logging.INFO' to 'tf.compat.v1.logging.INFO'
INFO line 163:2: Renamed 'tf.app.run' to 'tf.compat.v1.app.run'
TensorFlow 2.0 Upgrade Script
-----------------------------
Converted 1 files
Detected 0 issues that require attention
--------------------------------------------------------------------------------


Make sure to read the detailed log 'report.txt'

Kod için bir düzeltme bulamazsa komut dosyası hataları yazdırır.

dizin ağacı

Bu basit örnek de dahil olmak üzere tipik projeler, birden fazla dosya kullanacaktır. Genellikle bir paketin tamamını güncellemek istersiniz, böylece komut dosyası bir dizin ağacında da çalıştırılabilir:

# update the .py files and copy all the other files to the outtree
!tf_upgrade_v2 \
    --intree models/samples/cookbook/regression/ \
    --outtree regression_v2/ \
    --reportfile tree_report.txt
INFO line 82:10: tf.estimator.LinearRegressor: Default value of loss_reduction has been changed to SUM_OVER_BATCH_SIZE; inserting old default value tf.keras.losses.Reduction.SUM.

INFO line 105:2: Renamed 'tf.logging.set_verbosity' to 'tf.compat.v1.logging.set_verbosity'
INFO line 105:27: Renamed 'tf.logging.INFO' to 'tf.compat.v1.logging.INFO'
INFO line 106:2: Renamed 'tf.app.run' to 'tf.compat.v1.app.run'
INFO line 38:8: Renamed 'tf.feature_column.input_layer' to 'tf.compat.v1.feature_column.input_layer'
INFO line 43:10: Renamed 'tf.layers.dense' to 'tf.compat.v1.layers.dense'
INFO line 46:17: Renamed 'tf.layers.dense' to 'tf.compat.v1.layers.dense'
INFO line 57:17: tf.losses.mean_squared_error requires manual check. tf.losses have been replaced with object oriented versions in TF 2.0 and after. The loss function calls have been converted to compat.v1 for backward compatibility. Please update these calls to the TF 2.0 versions.
INFO line 57:17: Renamed 'tf.losses.mean_squared_error' to 'tf.compat.v1.losses.mean_squared_error'
INFO line 61:15: Added keywords to args of function 'tf.shape'
INFO line 62:15: Changed tf.to_float call to tf.cast(..., dtype=tf.float32).
INFO line 65:40: Renamed 'tf.train.AdamOptimizer' to 'tf.compat.v1.train.AdamOptimizer'
INFO line 68:39: Renamed 'tf.train.get_global_step' to 'tf.compat.v1.train.get_global_step'
INFO line 83:9: tf.metrics.root_mean_squared_error requires manual check. tf.metrics have been replaced with object oriented versions in TF 2.0 and after. The metric function calls have been converted to compat.v1 for backward compatibility. Please update these calls to the TF 2.0 versions.
INFO line 83:9: Renamed 'tf.metrics.root_mean_squared_error' to 'tf.compat.v1.metrics.root_mean_squared_error'
INFO line 142:23: Renamed 'tf.train.AdamOptimizer' to 'tf.compat.v1.train.AdamOptimizer'
INFO line 162:2: Renamed 'tf.logging.set_verbosity' to 'tf.compat.v1.logging.set_verbosity'
INFO line 162:27: Renamed 'tf.logging.INFO' to 'tf.compat.v1.logging.INFO'
INFO line 163:2: Renamed 'tf.app.run' to 'tf.compat.v1.app.run'
INFO line 58:10: tf.estimator.LinearRegressor: Default value of loss_reduction has been changed to SUM_OVER_BATCH_SIZE; inserting old default value tf.keras.losses.Reduction.SUM.

INFO line 101:2: Renamed 'tf.logging.set_verbosity' to 'tf.compat.v1.logging.set_verbosity'
INFO line 101:27: Renamed 'tf.logging.INFO' to 'tf.compat.v1.logging.INFO'
INFO line 102:2: Renamed 'tf.app.run' to 'tf.compat.v1.app.run'
INFO line 72:10: tf.estimator.DNNRegressor: Default value of loss_reduction has been changed to SUM_OVER_BATCH_SIZE; inserting old default value tf.keras.losses.Reduction.SUM.

INFO line 96:2: Renamed 'tf.logging.set_verbosity' to 'tf.compat.v1.logging.set_verbosity'
INFO line 96:27: Renamed 'tf.logging.INFO' to 'tf.compat.v1.logging.INFO'
INFO line 97:2: Renamed 'tf.app.run' to 'tf.compat.v1.app.run'
WARNING line 125:15: Changing dataset.make_one_shot_iterator() to tf.compat.v1.data.make_one_shot_iterator(dataset). Please check this transformation.

INFO line 40:7: Renamed 'tf.test.mock' to 'tf.compat.v1.test.mock'
TensorFlow 2.0 Upgrade Script
-----------------------------
Converted 7 files
Detected 1 issues that require attention
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
File: models/samples/cookbook/regression/automobile_data.py
--------------------------------------------------------------------------------
models/samples/cookbook/regression/automobile_data.py:125:15: WARNING: Changing dataset.make_one_shot_iterator() to tf.compat.v1.data.make_one_shot_iterator(dataset). Please check this transformation.



Make sure to read the detailed log 'tree_report.txt'

Yaklaşık bir uyarı Not dataset.make_one_shot_iterator fonksiyonu.

Artık komut dosyası TensorFlow 2.x ile çalışıyor:

Çünkü Not tf.compat.v1 modülü TF 1.15 dahildir, dönüştürülen komut da TensorFlow 1.15 çalışır.

(cd regression_v2 && python custom_regression.py 2>&1) | tail
I0922 22:16:42.778216 140254758430528 estimator.py:2074] Saving dict for global step 1000: global_step = 1000, loss = 651.5428, rmse = 3.684265
INFO:tensorflow:Saving 'checkpoint_path' summary for global step 1000: /tmp/tmpk2_4r192/model.ckpt-1000
I0922 22:16:42.817190 140254758430528 estimator.py:2135] Saving 'checkpoint_path' summary for global step 1000: /tmp/tmpk2_4r192/model.ckpt-1000
Tensor("IteratorGetNext:25", shape=(None,), dtype=float64, device=/device:CPU:0)
Tensor("Squeeze:0", shape=(None,), dtype=float32)

********************************************************************************

RMS error for the test set: $3684

Detaylı rapor

Komut dosyası ayrıca ayrıntılı değişikliklerin bir listesini de bildirir. Bu örnekte, muhtemelen güvenli olmayan bir dönüşüm buldu ve dosyanın üstüne bir uyarı ekledi:

head -n 20 tree_report.txt
TensorFlow 2.0 Upgrade Script
-----------------------------
Converted 7 files
Detected 1 issues that require attention
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
File: models/samples/cookbook/regression/automobile_data.py
--------------------------------------------------------------------------------
models/samples/cookbook/regression/automobile_data.py:125:15: WARNING: Changing dataset.make_one_shot_iterator() to tf.compat.v1.data.make_one_shot_iterator(dataset). Please check this transformation.

================================================================================
Detailed log follows:

================================================================================
================================================================================
Input tree: 'models/samples/cookbook/regression/'
================================================================================
--------------------------------------------------------------------------------
Processing file 'models/samples/cookbook/regression/__init__.py'
 outputting to 'regression_v2/__init__.py'

Yine yaklaşık bir uyarı Not Dataset.make_one_shot_iterator function .

Diğer durumlarda, çıktı önemsiz olmayan değişikliklerin gerekçesini açıklayacaktır:

%%writefile dropout.py
import tensorflow as tf

d = tf.nn.dropout(tf.range(10), 0.2)
z = tf.zeros_like(d, optimize=False)
Writing dropout.py
!tf_upgrade_v2 \
  --infile dropout.py \
  --outfile dropout_v2.py \
  --reportfile dropout_report.txt > /dev/null
cat dropout_report.txt
TensorFlow 2.0 Upgrade Script
-----------------------------
Converted 1 files
Detected 0 issues that require attention
--------------------------------------------------------------------------------
================================================================================
Detailed log follows:

================================================================================
--------------------------------------------------------------------------------
Processing file 'dropout.py'
 outputting to 'dropout_v2.py'
--------------------------------------------------------------------------------

3:4: INFO: Changing keep_prob arg of tf.nn.dropout to rate, and recomputing value.

4:4: INFO: Renaming tf.zeros_like to tf.compat.v1.zeros_like because argument optimize is present. tf.zeros_like no longer takes an optimize argument, and behaves as if optimize=True. This call site specifies something other than optimize=True, so it was converted to compat.v1.
--------------------------------------------------------------------------------

İşte değiştirilmiş dosya içerikleri, komut dosyasının taşınan ve yeniden adlandırılan argümanlarla başa çıkmak için argüman adlarını nasıl eklediğine dikkat edin:

cat dropout_v2.py
import tensorflow as tf

d = tf.nn.dropout(tf.range(10), rate=1 - (0.2))
z = tf.compat.v1.zeros_like(d, optimize=False)

Daha büyük bir proje birkaç hata içerebilir. Örneğin, derin laboratuvar modelini dönüştürün:

!tf_upgrade_v2 \
    --intree models/research/deeplab \
    --outtree deeplab_v2 \
    --reportfile deeplab_report.txt > /dev/null

Çıktı dosyalarını üretti:

ls deeplab_v2
README.md   datasets        input_preprocess.py        train.py
__init__.py deeplab_demo.ipynb  local_test.sh          utils
common.py   eval.py         local_test_mobilenetv2.sh  vis.py
common_test.py  export_model.py     model.py
core        g3doc           model_test.py

Ama hatalar vardı. Rapor, bu çalışmadan önce neyi düzeltmeniz gerektiğini belirlemenize yardımcı olacaktır. İşte ilk üç hata:

cat deeplab_report.txt | grep -i models/research/deeplab | grep -i error | head -n 3
models/research/deeplab/eval.py:28:7: ERROR: Using member tf.contrib.slim in deprecated module tf.contrib. tf.contrib.slim cannot be converted automatically. tf.contrib will not be distributed with TensorFlow 2.0, please consider an alternative in non-contrib TensorFlow, a community-maintained repository such as tensorflow/addons, or fork the required code.
models/research/deeplab/eval.py:146:8: ERROR: Using member tf.contrib.metrics.aggregate_metric_map in deprecated module tf.contrib. tf.contrib.metrics.aggregate_metric_map cannot be converted automatically. tf.contrib will not be distributed with TensorFlow 2.0, please consider an alternative in non-contrib TensorFlow, a community-maintained repository such as tensorflow/addons, or fork the required code.
models/research/deeplab/export_model.py:25:7: ERROR: Using member tf.contrib.slim in deprecated module tf.contrib. tf.contrib.slim cannot be converted automatically. tf.contrib will not be distributed with TensorFlow 2.0, please consider an alternative in non-contrib TensorFlow, a community-maintained repository such as tensorflow/addons, or fork the required code.

"Güvenli mod

Dönüşüm komut dosyası, aynı zamanda, daha az invazif SAFETY sadece kullanım için ithalat değiştirir modu tensorflow.compat.v1 modülü:

cat dropout.py
import tensorflow as tf

d = tf.nn.dropout(tf.range(10), 0.2)
z = tf.zeros_like(d, optimize=False)
tf_upgrade_v2 --mode SAFETY --infile dropout.py --outfile dropout_v2_safe.py > /dev/null
cat dropout_v2_safe.py
import tensorflow.compat.v1 as tf

d = tf.nn.dropout(tf.range(10), 0.2)
z = tf.zeros_like(d, optimize=False)

Gördüğünüz gibi bu, kodunuzu yükseltmez, ancak TensorFlow 1 kodunun TensorFlow 2 ikili dosyalarına karşı çalışmasına izin verir. Bunun, kodunuzun desteklenen TF 2.x davranışlarını çalıştırdığı anlamına gelmediğini unutmayın!

uyarılar

  • Bu betiği çalıştırmadan önce kodunuzun bölümlerini manuel olarak güncellemeyin. Özellikle, gibi yeniden sıralanmış argümanları vardı fonksiyonları tf.argmax veya tf.batch_to_space komut neden yanlış varolan kodu mismap anahtar kelime argümanları ekleyin.

  • Senaryo olduğunu varsayar tensorflow kullanılarak alınır import tensorflow as tf veya import tensorflow.compat.v1 as tf .

  • Bu komut dosyası, bağımsız değişkenleri yeniden sıralamaz. Bunun yerine, komut dosyası, bağımsız değişkenleri yeniden sıralanmış işlevlere anahtar sözcük bağımsız değişkenleri ekler.

  • Check out tf2up.ml bir GitHub depoda Jupyter defterleri ve Python dosyaları yükseltmek için uygun bir araç için.

Yükseltme komut hataları veya yapmak özellik istekleri bildirmek için, üzerinde bir sorunu bulunun GitHub'dan .