使用 Cloud Healthcare API 將 FHIR 臨床資料去識別化


本教學課程適用於醫療照護和生命科學機構的研究人員、資料科學家和 IT 團隊,說明如何使用 Cloud Healthcare API快速醫療照護互通資源 (FHIR) 去識別化作業,從 FHIR 臨床資料中移除或修改個人識別資訊 (PII),包括受保護的健康資訊 (PHI)。將醫療資料去識別化有助於保護病患隱私,並準備好用於研究、資料共用和機器學習的醫療照護資料。

本教學課程假設您具備 Linux 的基本知識。此外,對 Google Cloud 和FHIR 規格有基本瞭解,並知道 FHIR 規格在電子健康記錄 (EHR) 系統中的用途,也會很有幫助。請在 Cloud Shell 中執行本教學課程中的所有指令。

目標

  • 建立 Cloud Healthcare API 資料集FHIR 儲存庫
  • 將 FHIR 資料匯入 Cloud Healthcare API FHIR 儲存庫。
  • 使用 Cloud Healthcare API 的 FHIR 去識別化作業,移除或修改 FHIR 儲存庫中 FHIR 執行個體的 PII 和 PHI。
  • 使用 curl 指令列工具,透過 Cloud Healthcare API 呼叫 FHIR 去識別化作業。

費用

本教學課程使用下列 Google Cloud的計費元件:

如要根據預測用量估算費用,請使用 Pricing Calculator

事前準備

所有 Cloud Healthcare API 用量都會發生在Google Cloud 專案的環境中。專案是建立、啟用及使用所有Google Cloud 服務的基本要件,例如管理 API、啟用計費功能、新增及移除協作者,以及管理 Google Cloud資源的權限。請按照下列步驟建立 Google Cloud 專案,或選取您已建立的專案。

  1. In the Google Cloud console, go to the project selector page.

    Go to project selector

  2. Select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.
  3. Verify that billing is enabled for your Google Cloud project.

  4. Enable the Cloud Healthcare API.

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    Enable the API

  5. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  6. 在 Cloud Shell 中執行 gcloud components update 指令,確認您使用的是最新版 gcloud CLI,其中包含 Cloud Healthcare API 相關功能。

完成本文所述工作後,您可以刪除已建立的資源,避免繼續計費。詳情請參閱清除所用資源一節。

建立 IAM 服務帳戶

本教學課程需要「醫療保健資料集管理員」、「FHIR 管理員」和「FHIR 資源編輯者」角色。請按照下列步驟建立服務帳戶並指派正確的角色:

  1. 建立服務帳戶
  2. 將角色指派給服務帳戶:

    • Healthcare 資料集管理員
    • Healthcare FHIR 管理員
    • Healthcare FHIR 資源編輯者
  3. 建立並下載服務帳戶 JSON 金鑰

  4. 啟用服務帳戶金鑰:

    gcloud auth activate-service-account --key-file=path-to-key-file
    

    輸出內容如下:

    Activated service account credentials for: [key-name@project-name.iam.gserviceaccount.com]
    
    • key-name 是您指派給服務帳戶金鑰的名稱。
    • project-name 是您的 Google Cloud 專案名稱。

取得 OAuth 2.0 存取權杖

如要使用 Cloud Healthcare API 擷取資料,您需要 OAuth 2.0 存取權杖,本教學課程中的指令會為您取得這項權杖。在本教學課程中,部分 Cloud Healthcare API 要求範例會使用 curl 指令列工具。這些範例會使用 gcloud auth print-access-token 指令取得 OAuth 2.0 不記名憑證,並將該憑證納入要求的授權標頭。如要進一步瞭解這個指令,請參閱 gcloud auth application-default print-access-token

設定 FHIR 資料集以進行去識別化

每個 FHIR 資源都是類似 JSON 的物件,內含鍵/值組合。部分元素是標準化元素,其他元素則是任意文字。您可以使用去識別化作業執行下列操作:

  • 移除 FHIR 資源中特定鍵的值。
  • 處理非結構化文字,只移除 PII 元素,文字中的其餘內容則維持不變。

對資料集去識別化時,目的地資料集不得在您呼叫去識別化 API 前存在。去識別化作業會建立目的地資料集。

對單一 FHIR 儲存庫執行去識別化作業時,您必須先建立目的地資料集,才能發出去識別化 API 呼叫。

來源資料集、FHIR 儲存庫和目的地資料集的 FHIR 儲存庫必須位於相同的 Google Cloud 專案。執行去識別化作業時,系統會在與來源資料集和 FHIR 儲存庫相同的 Google Cloud 專案中,建立目的地資料集和 FHIR 儲存庫。

如要產生合成 FHIR 資料以用於本教學課程,可以使用 Synthea,以 FHIR STU3 格式產生合成資料,然後將產生的資料複製到 Cloud Storage bucket,再匯入 Cloud Healthcare API FHIR 儲存庫。Synthea 不會產生含有任意或非結構化文字元件的 FHIR 資料,因此無法用來探索去識別化作業的這些層面。

在本教學課程中,您會按照下列程序,將範例 FHIR 資料匯入 FHIR 儲存庫。

  1. 為專案和位置設定環境變數,以便儲存資料集、FHIR 存放區和 FHIR 資料。指派給環境變數的值是範例值,如下所示:

    export PROJECT_ID=MyProj
    export REGION=us-central1
    export SOURCE_DATASET_ID=dataset1
    export FHIR_STORE_ID=FHIRstore1
    export DESTINATION_DATASET_ID=deid-dataset1
    

    先前範例中宣告的環境變數定義如下:

    • $PROJECT_ID 是您的 Google Cloud 專案 ID。
    • $REGION 是您建立 Cloud Healthcare API 資料集的 Google Cloud 地區。
    • $SOURCE_DATASET_ID 是儲存來源資料的 Cloud Healthcare API 資料集名稱。
    • $FHIR_STORE_ID 是來源 Cloud Healthcare API FHIR 存放區的名稱。
    • $DESTINATION_DATASET_ID 是 Cloud Healthcare API 目的地資料集的名稱,去識別化資料會寫入該資料集。

    您也會在本教學課程稍後使用這些環境變數。

  2. 建立 Cloud Healthcare API 資料集:

    gcloud healthcare datasets create $SOURCE_DATASET_ID --location=$REGION
    

    輸出內容類似於下列內容,其中 [OPERATION_NUMBER] 是用於追蹤要求的資料集建立作業 ID:

    Create request issued for: $SOURCE_DATASET_ID
    
    Waiting for operation [OPERATION_NUMBER] to complete...done.
    Created dataset $SOURCE_DATASET_ID.
    

    上述指令會在 $REGION 區域中建立名為 $SOURCE_DATASET_ID 的來源資料集。

  3. 使用下列指令建立 FHIR 儲存庫:

    gcloud healthcare fhir-stores create $FHIR_STORE_ID \
        --dataset=$SOURCE_DATASET_ID --location=$REGION
    

    上述指令會在資料集 $SOURCE_DATASET_ID 中建立名為 $FHIR_STORE_ID 的 FHIR 儲存庫。

  4. 使用下列指令,透過 FHIR create 函式將 FHIR Patient 資源新增至 FHIR 存放區:

    curl -X POST \
        -H "Authorization: Bearer $(gcloud auth print-access-token)" \
        -H "Content-Type: application/fhir+json; charset=utf-8" \
        --data "{
           \"address\": [
        {
          \"city\": \"Anycity\",
          \"district\": \"Anydistrict\",
          \"line\": [
            \"123 Main Street\"
          ],
          \"period\": {
            \"start\": \"1990-12-05\"
          },
          \"postalCode\": \"12345\",
          \"state\": \"CA\",
          \"text\": \"123 Main Street Anycity, Anydistrict, CA 12345\",
          \"use\": \"home\"
        }
      ],
              \"name\": [
            {
              \"family\": \"Smith\",
              \"given\": [
                \"Darcy\"
              ],
              \"use\": \"official\"
            }
          ],
          \"gender\": \"female\",
          \"birthDate\": \"1980-12-05\",
          \"resourceType\": \"Patient\"
        }" \
    "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/fhirStores/$FHIR_STORE_ID/fhir/Patient"
    

    指令的引數對應至範例 FHIR 資源,也就是 FHIR Patient 資源

    {
      "address": [
        {
          "city": "Anycity",
          "district": "Anydistrict",
          "line": [
            "123 Main Street"
          ],
          "period": {
            "start": "1990-12-05"
          },
          "postalCode": "12345",
          "state": "CA",
          "text": "123 Main Street Anycity, Anydistrict, CA 12345",
          "use": "home"
        }
      ],
      "name": [
        {
          "family": "Smith",
          "given": [
            "Darcy"
          ],
    "use": "official"
        }
      ],
    "gender": "female",
    "birthDate": "1980-12-05",
     "resourceType": "Patient"
    }
    

    如果要求成功,伺服器會傳回類似下列內容的輸出內容:

    {
      "address": [
        {
          "city": "Anycity",
          "district": "Anydistrict",
          "line": [
            "123 Main Street"
          ],
          "period": {
            "start": "1990-12-05"
          },
          "postalCode": "12345",
          "state": "CA",
          "text": "123 Main Street Anycity, Anydistrict, CA 12345",
          "use": "home"
        }
      ],
      "birthDate": "1980-12-05",
      "gender": "female",
      "id": "0359c226-5d63-4845-bd55-74063535e4ef",
      "meta": {
        "lastUpdated": "2020-02-08T00:03:21.745220+00:00",
        "versionId": "MTU4MTEyMDIwMTc0NTIyMDAwMA"
      },
      "name": [
        {
          "family": "Smith",
          "given": [
            "Darcy"
          ],
          "use": "official"
        }
      ],
      "resourceType": "Patient"
    }
    

    上述 curl 指令會在來源 FHIR 存放區中插入新的 Patient 資源。輸出內容會產生病患 ID (id)。病患 ID 是去識別化的英數字串,用於 FHIR Encounter 資源,連結至 FHIR Patient 資源。

  5. 使用下列指令,透過 FHIR create 函式將 FHIR Encounter 資源新增至 FHIR 儲存庫。在指令中,將 subject.reference 值替換為先前 curl 指令輸出中的病患 ID 值:

    curl -X POST \
        -H "Authorization: Bearer $(gcloud auth print-access-token)" \
        -H "Content-Type: application/fhir+json; charset=utf-8" \
        --data "{
          \"status\": \"finished\",
          \"class\": {
            \"system\": \"http://hl7.org/fhir/v3/ActCode\",
            \"code\": \"IMP\",
            \"display\": \"inpatient encounter\"
          },
          \"reason\": [
            {
              \"text\": \"Mrs. Smith is a 39-year-old female who has a past
    medical history significant for a myocardial infarction. Catheterization
    showed a possible kink in one of her blood vessels.\"
            }
          ],
          \"subject\": {
            \"reference\":
    \"Patient/0359c226-5d63-4845-bd55-74063535e4ef\"
          },
          \"resourceType\": \"Encounter\"
        }" \
    
    "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/fhirStores/$FHIR_STORE_ID/fhir/Encounter"
    

    指令的引數對應範例 FHIR 資源,也就是 FHIR Encounter 資源

    {
          "status": "finished",
          "class": {
            "system": "http://hl7.org/fhir/v3/ActCode",
            "code": "IMP",
            "display": "inpatient encounter"
          },
          "reason": [
            {
              "text": "Mrs. Smith is a 39-year-old female who has a past medical
    history significant for a myocardial infarction. Catheterization showed a
    possible kink in one of her blood vessels."
            }
          ],
          "subject": {
            "reference": "Patient/0359c226-5d63-4845-bd55-74063535e4ef"
          },
          "resourceType": "Encounter"
        }
    

    如果要求成功,伺服器會傳回類似下列內容的輸出內容:

    {
      "class": {
        "code": "IMP",
        "display": "inpatient encounter",
        "system": "http://hl7.org/fhir/v3/ActCode"
      },
      "id": "0038a95f-3c11-4163-8c2e-10842b6b1547",
      "meta": {
        "lastUpdated": "2020-02-12T00:39:16.822443+00:00",
        "versionId": "MTU4MTQ2Nzk1NjgyMjQ0MzAwMA"
      },
      "reason": [
        {
          "text": "Mrs. Smith is a 39-year-old female who has a past medical history
    significant for a myocardial infarction. Catheterization showed a possible
    kink in one of her blood vessels."
        }
      ],
      "resourceType": "Encounter",
      "status": "finished",
      "subject": {
        "reference": "Patient/0359c226-5d63-4845-bd55-74063535e4ef"
      }
    

    上述 curl 指令會在來源 FHIR 存放區中插入新的 Encounter 資源。

將 FHIR 資料去識別化

接著,您要對插入來源 FHIR 儲存庫的 FHIR 資料執行去識別化作業。 您會遮蓋或轉換結構化欄位中的所有 PII 元素,例如 Patient.namePatient.address 欄位。您也可以將文字中非結構化資料的 PII 元素去識別化,例如 Encounter.reason.text

您可以選擇將結果資料直接匯出至 BigQuery,以進行分析和機器學習訓練。

這項去識別化設定可用於人口健康分析或類似用途。在本教學課程中,您可以將去識別化的結構化資料移至 BigQuery,評估大規模趨勢。您可能不需要非結構化欄位,因為這類欄位難以大規模正規化和分析。不過,本教學課程仍會納入非結構化欄位,以供參考。

將 FHIR 資料去識別化有許多潛在用途,Cloud Healthcare API 也支援許多設定選項。如需更多資訊,包括範例 curl 指令和不同情境的 PowerShell 工具範例,請參閱去識別化 FHIR 資料

含有日期的欄位會透過日期轉移轉換,這項技術會將 FHIR 資源中的所有日期,以一致的隨機量變更。日期偏移功能可確保 FHIR 資源內的一致性,因此可保留醫療相關詳細資料 (例如病患年齡和預約間隔時間),同時不會揭露病患的識別資訊。非結構化欄位中的所有 ID 也會轉換。

以下範例也包含 name 欄位的雜湊轉換。雜湊是一種單向加密技術,可確保名稱一律轉換為相同輸出值,並為資料集中的多筆記錄產生一致的病患姓名輸出值。這項作業會遮蓋 PII,同時保留資源之間的連結。

在本範例中,提供的加密金鑰 U2FsdGVkX19bS2oZsdbK9X5zi2utBn22uY+I2Vo0zOU= 是以 AES 加密的 256 位元 Base64 編碼金鑰範例,使用下列指令產生。

echo -n "test" | openssl enc -e -aes-256-ofb -a -salt

系統會要求您輸入密碼。輸入您選擇的密碼。

  1. 使用 curl 指令,遮蓋或轉換結構化欄位 (例如 nameaddress 欄位) 中的所有 PII 元素,以及轉換非結構化欄位中的所有 ID。

    curl -X POST \
        -H "Authorization: Bearer "$(gcloud auth print-access-token) \
        -H "Content-Type: application/json; charset=utf-8" \
        --data "{
          'destinationDataset':
    'projects/$PROJECT_ID/locations/$REGION/datasets/$DESTINATION_DATASET_ID',
          'config': {
          'fhir': {
              'fieldMetadataList': {
                'paths': [
                  'Patient.address.state',
                  'Patient.address.line',
                  'Patient.address.text',
                  'Patient.address.postalCode'
                ],
                'action': 'TRANSFORM'
              },
             'fieldMetadataList': {
               'paths': [
                 'Encounter.reason.text'
               ],
               'action': 'INSPECT_AND_TRANSFORM'
             },
           'text': {
             'transformations': [
               {
                 'infoTypes': [],
                 'replaceWithInfoTypeConfig': {}
               }
             ]
           },
              'fieldMetadataList': {
                'paths': [
                  'Patient.name.family',
                  'Patient.name.given'
                ],
                'action': 'TRANSFORM'
              },
            'text': {
              'transformations': {
                'infoTypes': [
                  'PERSON_NAME'
                ],
                'cryptoHashConfig': {
                  'cryptoKey':
    'U2FsdGVkX19bS2oZsdbK9X5zi2utBn22uY+I2Vo0zOU='
                }
              }
            },
              'fieldMetadataList': {
                'paths': [
                  'Patient.birthDate',
                  'Patient.address.period.start'
                ],
                'action': 'TRANSFORM'
              },
            'text': {
              'transformations': {
                'infoTypes': [
                  'DATE'
                ],
                'dateShiftConfig': {
                  'cryptoKey':
    'U2FsdGVkX19bS2oZsdbK9X5zi2utBn22uY+I2Vo0zOU='
                }
              }
            }
          }
        }"
    "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID:deidentify"
    

    如果要求成功,伺服器會傳回 JSON 格式的回應,如下所示:

    {
      "name": "projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/OPERATION_NAME"
    }
    

    在上述範例中,curl 指令會透過下列方式轉換值,進而對 FHIR 資源去識別化:

    • 刪減 Patient.address.line 值、Patient.address.text 值和 Patient.address.postalCode 值。
    • Patient.name.family 值替換為雜湊值,並將 Patient.name.given 值替換為雜湊值。
    • Patient.birthDate 欄位和 period.start 欄位中的值,替換為日期偏移 100 天後產生的值。
    • Encounter.reason.text 欄位中,將病患的姓氏替換為雜湊值,並將病患的年齡替換為字面值 [AGE]
  2. 前述作業的回應包含作業名稱。使用 get 方法追蹤作業狀態:

    curl -X GET \
        -H "Authorization: Bearer "$(gcloud auth print-access-token) \
        -H "Content-Type: application/json; charset=utf-8" \
    "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/operations/OPERATION_NAME"
    

    如果要求成功,伺服器會以 JSON 格式傳回回應。去識別化程序完成後,回應中會包含 "done": true

    {
      "name": "projects/$PROJECT_ID/locations/$REGION/datasets/$SOURCE_DATASET_ID/operations/OPERATION_NAME",
      "metadata": {
        "@type": "type.googleapis.com/google.cloud.healthcare.v1.OperationMetadata",
        "apiMethodName": "google.cloud.healthcare.v1.dataset.DatasetService.DeidentifyDataset",
        "createTime": "2018-01-01T00:00:00Z",
        "endTime": "2018-01-01T00:00:00Z"
      },
      "done": true,
      "response": {
        "@type": "...",
        "successStoreCount": "SUCCESS_STORE_COUNT"
      }
    }
    

    上述指令會傳回去識別化作業的狀態。

  3. 使用病患 ID 執行下列指令,在新目的地資料集中取得 FHIR Patient 資源的詳細資料:

    curl -X GET \
         -H "Authorization: Bearer $(gcloud auth print-access-token)" \
     "https://healthcare.googleapis.com/v1/projects/$PROJECT_ID/locations/$REGION/datasets/$DESTINATION_DATASET_ID/fhirStores/$FHIR_STORE_ID/fhir/Patient/a952e409-2403-43e6-9815-cb78c5b5eca2/\$everything"
    

    如果要求成功,伺服器會傳回類似下方的回應,這是原始 FHIR 資源的去識別化版本:

      "entry": [\
        {\
          "resource": {\
            "class": {\
              "code": "IMP",\
              "display": "inpatient encounter",\
              "system": "http://hl7.org/fhir/v3/ActCode"\
            },\
            "id": "0038a95f-3c11-4163-8c2e-10842b6b1547",\
            "reason": [\
              {\
                "text": "Mr. NlVBV12Hhb5DD8WNqlTpXboFxzlUSlqAmYDet/jIViQ= is a [AGE]
    gentleman who has a past medical history significant for a myocardial
    infarction. Catheterization showed a possible kink in one of his vessels."\
              }\
            ],\
            "resourceType": "Encounter",\
            "status": "finished",\
            "subject": {\
              "reference": "Patient/0359c226-5d63-4845-bd55-74063535e4ef"\
            }\
          }\
        },\
        {\
          "resource": {\
            "address": [\
              {\
                "city": "Anycity",\
                "district": "Anydistrict",\
                "line": [\
                  ""\
                ],\
                "period": {\
                  "start": "1990-09-23"\
                },\
                "postalCode": "",\
                "state": "",\
                "text": "",\
                "use": "home"\
              }\
            ],\
            "birthDate": "1980-09-23",\
            "gender": "female",\
            "id": "0359c226-5d63-4845-bd55-74063535e4ef",\
            "name": [\
              {\
                "family": "NlVBV12Hhb5DD8WNqlTpXboFxzlUSlqAmYDet/jIViQ=",\
                "given": [\
                  "FSH4e the project.D/IGb80a1rS0L0kqfC3DCDt6//17VPhIkOzH2pk="\
                ],\
                "use": "official"\
              }\
            ],\
            "resourceType": "Patient"\
          }\
        }\
      ],\
      "resourceType": "Bundle",\
      "total": 2,\
      "type": "searchset"\
    }
    

    上述指令會驗證去識別化作業是否成功去識別化 FHIR 資源。

清除所用資源

如要避免系統向您的 Google Cloud 帳戶收取本教學課程中所用資源的相關費用,請刪除含有該項資源的專案,或者保留專案但刪除個別資源。

刪除專案

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

刪除個別資源

  • 刪除目的地資料集:

    gcloud healthcare datasets delete $DESTINATION_DATASET_ID
    

後續步驟