解决具有不同数据类型分类特征的 Keras 函数模型的类型转换错误
我正在创建一个模型,该模型导入分类字符串和数字数据以及连续特征的 csv,以预测学生是否会毕业。IndexAgeHousehold_SizeGender
我正在创建一个模型,该模型导入分类字符串和数字数据以及连续特征的 csv 来预测学生是否会毕业。
指数 | 年龄 | 房子大小 | 性别 | 婚姻状况 | 职业 | 收入水平 | 已毕业 |
---|---|---|---|---|---|---|---|
0 | 三十二 | 4 | 女性 | 已婚 | 护士 | 60000 | 1 |
1 | 四十五 | 2 | 男性 | 离婚 | 老师 | 80000 | 1 |
2 | 二十八 | 1 | 女性 | 单身的 | 软件工程师 | 120000 | 1 |
3 | 62 | 2 | 男性 | 已婚 | 已退休 | 20000 | 1 |
4 | 三十五 | 3 | 女性 | 已婚 | 律师 | 160000 | 1 |
图层创建函数定义
def get_normalization_layer(name, dataset):
# Create a Normalization layer for the feature.
norm=name+'_norm'
normalizer = layers.Normalization(axis=None, name=norm)
# Prepare a Dataset that only yields the feature.
feature_ds = dataset.map(lambda x, y: x[name])
# Learn the statistics of the data.
normalizer.adapt(feature_ds)
return normalizer
def get_category_encoding_layer(name, dataset, dtype, max_tokens=None):
# Create a layer that turns strings into integer indices.
ind=name+'_index'
if dtype == 'string':
index = layers.StringLookup(max_tokens=max_tokens, name=ind)
# Otherwise, create a layer that turns integer values into integer indices.
else:
index = layers.IntegerLookup(max_tokens=max_tokens, name=ind)
# Prepare a `tf.data.Dataset` that only yields the feature.
feature_ds = dataset.map(lambda x, y: x[name])
# Learn the set of possible values and assign them a fixed integer index.
index.adapt(feature_ds)
# Encode the integer indices.
enc=name+'_encoding'
encoder = layers.CategoryEncoding(num_tokens=index.vocabulary_size(), name=enc)
# Apply multi-hot encoding to the indices. The lambda function captures the
# layer, so you can use them, or include them in the Keras Functional model later.
return lambda feature: encoder(index(feature))
模型创建
all_inputs = []
encoded_features = []
categorical_str_cols = ['Gender', 'Marital_Status', 'Occupation']
for header in categorical_str_cols:
categorical_col = tf.keras.Input(shape=(1,), name=header, dtype='string')
encoding_layer = get_category_encoding_layer(name=header,
dataset=train_ds,
dtype='string')
encoded_categorical_str_col = encoding_layer(categorical_col)
all_inputs.append(categorical_col)
encoded_features.append(encoded_categorical_str_col)
categorical_int_cols = ['Age', 'Household_Size']
for header in categorical_int_cols:
categorical_col = tf.keras.Input(shape=(1,), name=header, dtype='int64')
encoding_layer = get_category_encoding_layer(name=header,
dataset=train_ds,
dtype='int64')
encoded_categorical_int_col = encoding_layer(categorical_col)
all_inputs.append(categorical_col)
encoded_features.append(encoded_categorical_int_col)
# Numerical features.
for header in ['Income_Level']:
numeric_col = tf.keras.Input(shape=(1,), name=header)
normalization_layer = get_normalization_layer(header, train_ds)
encoded_numeric_col = normalization_layer(numeric_col)
all_inputs.append(numeric_col)
encoded_features.append(encoded_numeric_col)
all_features = tf.keras.layers.concatenate(encoded_features)
x = tf.keras.layers.Dense(32, activation="relu")(all_features)
x = tf.keras.layers.Dropout(0.5)(x)
output = tf.keras.layers.Dense(1)(x)
model = tf.keras.Model(all_inputs, output)
model.compile(optimizer='adam',
loss=tf.keras.losses.BinaryCrossentropy(from_logits=True),
metrics=["accuracy"])
模型图像
由于声誉太低,无法发布图片链接: 来自 plot_model 的模型图像
当我在 tf.dataset 上运行 model.fit 时,收到错误:
---------------------------------------------------------------------------
UnimplementedError Traceback (most recent call last)
Cell In[539], line 1
----> 1 model.fit(train_ds, epochs=10, validation_data=val_ds)
File ~\anaconda3\Lib\site-packages\keras\src\utils\traceback_utils.py:122, in filter_traceback.<locals>.error_handler(*args, **kwargs)
119 filtered_tb = _process_traceback_frames(e.__traceback__)
120 # To get the full stack trace, call:
121 # `keras.config.disable_traceback_filtering()`
--> 122 raise e.with_traceback(filtered_tb) from None
123 finally:
124 del filtered_tb
File ~\anaconda3\Lib\site-packages\tensorflow\python\eager\execute.py:53, in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
51 try:
52 ctx.ensure_initialized()
---> 53 tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
54 inputs, attrs, num_outputs)
55 except core._NotOkStatusException as e:
56 if name is not None:
UnimplementedError: Graph execution error:
Detected at node functional_27_1/Cast defined at (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "C:\Users\-\anaconda3\Lib\site-packages\ipykernel_launcher.py", line 17, in <module>
File "C:\Users\-\anaconda3\Lib\site-packages\traitlets\config\application.py", line 1075, in launch_instance
File "C:\Users\-\anaconda3\Lib\site-packages\ipykernel\kernelapp.py", line 701, in start
File "C:\Users\-\anaconda3\Lib\site-packages\tornado\platform\asyncio.py", line 205, in start
File "C:\Users\-\anaconda3\Lib\asyncio\windows_events.py", line 322, in run_forever
File "C:\Users\-\anaconda3\Lib\asyncio\base_events.py", line 641, in run_forever
File "C:\Users\-\anaconda3\Lib\asyncio\base_events.py", line 1987, in _run_once
File "C:\Users\-\anaconda3\Lib\asyncio\events.py", line 88, in _run
File "C:\Users\-\anaconda3\Lib\site-packages\ipykernel\kernelbase.py", line 534, in dispatch_queue
File "C:\Users\-\anaconda3\Lib\site-packages\ipykernel\kernelbase.py", line 523, in process_one
File "C:\Users\-\anaconda3\Lib\site-packages\ipykernel\kernelbase.py", line 429, in dispatch_shell
File "C:\Users\-\anaconda3\Lib\site-packages\ipykernel\kernelbase.py", line 767, in execute_request
File "C:\Users\-\anaconda3\Lib\site-packages\ipykernel\ipkernel.py", line 429, in do_execute
File "C:\Users\-\anaconda3\Lib\site-packages\ipykernel\zmqshell.py", line 549, in run_cell
File "C:\Users\-\anaconda3\Lib\site-packages\IPython\core\interactiveshell.py", line 3075, in run_cell
File "C:\Users\-\anaconda3\Lib\site-packages\IPython\core\interactiveshell.py", line 3130, in _run_cell
File "C:\Users\-\anaconda3\Lib\site-packages\IPython\core\async_helpers.py", line 129, in _pseudo_sync_runner
File "C:\Users\-\anaconda3\Lib\site-packages\IPython\core\interactiveshell.py", line 3334, in run_cell_async
File "C:\Users\-\anaconda3\Lib\site-packages\IPython\core\interactiveshell.py", line 3517, in run_ast_nodes
File "C:\Users\-\anaconda3\Lib\site-packages\IPython\core\interactiveshell.py", line 3577, in run_code
File "C:\Users\-\AppData\Local\Temp\ipykernel_5448\2809293729.py", line 1, in <module>
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\utils\traceback_utils.py", line 117, in error_handler
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\backend\tensorflow\trainer.py", line 318, in fit
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\backend\tensorflow\trainer.py", line 121, in one_step_on_iterator
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\backend\tensorflow\trainer.py", line 108, in one_step_on_data
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\backend\tensorflow\trainer.py", line 51, in train_step
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\utils\traceback_utils.py", line 117, in error_handler
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\layers\layer.py", line 882, in __call__
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\utils\traceback_utils.py", line 117, in error_handler
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\ops\operation.py", line 46, in __call__
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\utils\traceback_utils.py", line 156, in error_handler
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\models\functional.py", line 167, in call
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\models\functional.py", line 258, in _standardize_inputs
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\models\functional.py", line 218, in _convert_inputs_to_tensors
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\ops\core.py", line 743, in convert_to_tensor
File "C:\Users\-\anaconda3\Lib\site-packages\keras\src\backend\tensorflow\core.py", line 120, in convert_to_tensor
Cast int64 to string is not supported
[[{{node functional_27_1/Cast}}]] [Op:__inference_one_step_on_iterator_97454]
示例 tf.dataset 批次大小 3
{'Age': <tf.Tensor: shape=(3, 1), dtype=int64, numpy=
array([[23],
[29],
[31]], dtype=int64)>, 'Household_Size': <tf.Tensor: shape=(3, 1), dtype=int64, numpy=
array([[3],
[3],
[3]], dtype=int64)>, 'Gender': <tf.Tensor: shape=(3, 1), dtype=string, numpy=
array([[b'Female'],
[b'Female'],
[b'Female']], dtype=object)>, 'Marital_Status': <tf.Tensor: shape=(3, 1), dtype=string, numpy=
array([[b'Single'],
[b'Single'],
[b'Single']], dtype=object)>, 'Occupation': <tf.Tensor: shape=(3, 1), dtype=string, numpy=
array([[b'Server'],
[b'Nurse'],
[b'Retail Associate']], dtype=object)>, 'Income_Level': <tf.Tensor: shape=(3, 1), dtype=int64, numpy=
array([[30000],
[50000],
[30000]], dtype=int64)>}
tf.Tensor([1 1 1], shape=(3,), dtype=int64)
但是,如果我排除字符串分类层和数据,或者仅使用字符串层/数据,模型将成功运行其训练。我应该如何创建层,以便我可以在同一模型中同时拥有这两种数据类型?
-
我有一个建筑物放置项目,它不适用于 3D 房屋对象。所有对象都具有刚体和盒子碰撞器组件,而只有房屋预制对象才有子对象。我的 s...
我有一个建筑物放置项目,它不适用于 3D 房屋对象。所有对象都有刚体和盒子碰撞器组件,而只有房屋预制对象才有子对象。我的脚本如下:
BuildingManager 脚本:
public class BuildingManager : MonoBehaviour { private GameObject pendingObject; [SerializeField] private Material[] materials; public bool canPlace; void Update() { if (pendingObject != null) { UpDateMaterials(); pendingObject.transform.position = pos; if (Input.GetMouseButtonDown(0) && canPlace) { PlaceObject(); } } } public void PlaceObject() { pendingObject.GetComponent<MeshRenderer>().material = materials[2]; pendingObject = null; } public void UpDateMaterials() { if (canPlace) { pendingObject.GetComponent<MeshRenderer>().material = materials[0]; } if (!canPlace) { pendingObject.GetComponent<MeshRenderer>().material = materials[1]; } } }
CheckPlacement 脚本:
public class CheckPlacement : MonoBehaviour { BuildingManager buildingManager; void Start() { buildingManager = GameObject.Find("BuildingManager").GetComponent<BuildingManager>(); } private void OnTriggerEnter(Collider other) { if (other.gameObject.CompareTag("Building")) { Debug.Log("Can't Place Building"); buildingManager.canPlace = false; } } private void OnTriggerExit(Collider other) { if (other.gameObject.CompareTag("Building")) { Debug.Log("Can Place Building"); buildingManager.canPlace = true; } } }
这些脚本可以很好地与 Unity 的默认 3D 对象(如 3D 胶囊、球体、盒子对象)配合使用。例如,我尝试将胶囊对象与已经在地面(平面)上的房屋对象重叠。胶囊对象在与房屋对象碰撞时变为透明红色,当我将其拖到地面时,它变为透明绿色。
欢迎提出任何建议...
-
由于房屋对象有多个子对象,因此您需要更新所有网格渲染器。为此,请使用 GetComponentsInChildren 获取所有网格渲染器,并在更改材质时循环遍历这些渲染器。如果对象没有变化,您可以缓存网格渲染器以避免多次调用 GetComponents。
private MeshRenderer[] meshRenderers; private void Awake() { meshRenderers = pendingObject.GetComponentsInChildren<MeshRenderer>(); } ... private void UpdateMaterials() { if (canPlace) { UpdateMeshRenderersMaterial(materials[0]); } else { UpdateMeshRenderersMaterial(materials[1]); } } private void PlaceObject() { UpdateMeshRenderersMaterial(materials[2]); } private void UpdateMeshRenderersMaterial(Material material) { foreach (var meshRenderer in meshRenderers) { meshRenderer.material = material; } }
我不会每帧都更新材质(即使放置状态没有改变!),
canPlace
而是将其设为私有,只允许其他组件通过函数进行更改。这样,您就可以响应对象放置状态的变化,从而避免不必要地更改材质。我添加了一个强制更新参数,默认为 false,当该参数为 true 时,将强制更新材质。private bool canPlace; public void UpdatePlacementStatus(bool canPlace, bool forceUpdate = false) { if (forceUpdate || this.canPlace != canPlace) { this.canPlace = canPlace; UpdateMaterials(); } }
来自其他组件:
Debug.Log("Can't Place Building"); buildingManager.UpdatePlacementStatus(false);